日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

字符串的模式匹配(Java实现)

發(fā)布時間:2025/4/16 java 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 字符串的模式匹配(Java实现) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

  字符串的模式匹配

字串的定位操作通常稱做模式匹配,是各種串處理系統(tǒng)中最重要的操作之一。本文主要介紹兩種常用的實現(xiàn)算法:

  1、暴力匹配

  2、KMP算法

?

1.暴力匹配

  時間復(fù)雜度為O(n*m);n為主串長度,m為模式串長度

  算法的基本思想:

      從主串的起始位置(或指定位置)開始與模式串的第一個字符比較,若相等,則繼續(xù)逐個比較后續(xù)字符;否則從主串的下一個字符再重新和模式串的字符比較。依次類推,直到模式串成功匹配,返回主串中第一次出現(xiàn)模式串字符的位置,或者模式串匹配不成功,這里約定返回-1;

 

//偽代碼 int bruteForceStringMatch(String source, String pattern) {i = 0; j = 0;while(i < slen && j < plen){if(s[i] == p[j])++i; ++j;elsei = i - (j -1); //回溯上次匹配起始位置的后一位j = 0;}if(j == plen) return i - j; //匹配成功elsereturn -1; //匹配失敗 }

實現(xiàn)代碼:

1 public static int bruteForceStringMatch(String source, String pattern) 2 { 3 int slen = source.length(); 4 int plen = pattern.length(); 5 char[] s = source.toCharArray(); 6 char[] p = pattern.toCharArray(); 7 int i = 0; 8 int j = 0; 9 10 if(slen < plen) 11 return -1; //如果主串長度小于模式串,直接返回-1,匹配失敗 12 else 13 { 14 while(i < slen && j < plen) 15 { 16 if(s[i] == p[j]) //如果i,j位置上的字符匹配成功就繼續(xù)向后匹配 17 { 18 ++i; 19 ++j; 20 } 21 else 22 { 23 i = i - (j -1); //i回溯到主串上一次開始匹配下一個位置的地方 24 j = 0; //j重置,模式串從開始再次進(jìn)行匹配 25 } 26 } 27 if(j == plen) //匹配成功 28 return i - j; 29 else 30 return -1; //匹配失敗 31 } 32 } View Code

?

2.KMP算法

  KMP算法是D.E.Knuth、V.R.Pratt和J.H.Morris同時發(fā)現(xiàn),所以命名為KMP算法。

  此算法可以在O(n+m)的時間數(shù)量級上完成串的模式匹配。

  主要就是改進(jìn)了暴力匹配中i回溯的操作,KMP算法中當(dāng)一趟匹配過程中出現(xiàn)字符比較不等時,不直接回溯i,而是利用已經(jīng)得到的“部分匹配”的結(jié)果將模式串向右移動(j-next[k])的距離。稍后我們將詳細(xì)解釋next[k]的計算過程。

//偽代碼 int kmpStringMatch(String source, String pattern) {i = 0;j = 1;while(i < slen && j < plen){if(j == 0 || s[i] == p[j]) ++i; ++j;elsej = next[j]; }if(j == plen)return i - j;elsereturn -1; }

實現(xiàn)代碼:

1 public static int kmpStringMatch(String source, String pattern) 2 { 3 int i = 0; 4 int j = 0; 5 char[] s = source.toCharArray(); 6 char[] p = pattern.toCharArray(); 7 int slen = s.length; 8 int plen = p.length; 9 int[] next = getNext(p); 10 while(i < slen && j < plen) 11 { 12 if(j == -1 || s[i] == p[j]) 13 { 14 ++i; 15 ++j; 16 } 17 else 18 { 19 //如果j != -1且當(dāng)前字符匹配失敗,則令i不變, 20 //j = next[j],即讓pattern模式串右移j - next[j]個單位 21 j = next[j]; 22 } 23 } 24 if(j == plen) 25 return i - j; 26 else 27 return -1; 28 } View Code

?

那么問題來了,next[k]是怎么計算出來的呢?

關(guān)于next[k]數(shù)組的計算引出的兩種辦法,一種是遞歸,一種對遞歸優(yōu)化,第一種對應(yīng)的就是KMP算法,第二種就是優(yōu)化的KMP算法。

next函數(shù)值僅取決于模式串本身而和主串無關(guān)。

有很多講next函數(shù)值計算辦法的資料,在此我想用一種直觀的比較容易理解的辦法來表達(dá)。

舉個栗子:現(xiàn)在有一個模式串a(chǎn)bab

? ? 模式串的各個字串  ??? ? ? ? ? ? ? ? ? ? ?前綴 ? ? ? ? ? ? ? ? ? ? ??? ? ? ? ? ? ? ? ? ? 后綴 ? ? ? ? ? ? ? ? ? ?最大公共元素長度
anullnull0
abab0
abaa,aba,ba1
ababa,ab,abab,ab,bab2

?

?

?

?

next函數(shù)值的實現(xiàn):

private static int[] getNext(char[] p){/*** 已知next[j] = k, 利用遞歸的思想求出next[j+1]的值* 1.如果p[j] = p[k],則next[j+1] = next[k] + 1;* 2.如果p[j] != p[k],則令k = next[k],如果此時p[j] == p[k],則next[j+1] = k+1* 如果不相等,則繼續(xù)遞歸前綴索引,令k=next[k],繼續(xù)判斷,直至k=-1(即k=next[0])或者p[j]=p[k]為止*/int plen = p.length;int[] next = new int[plen];int k = -1;int j = 0;next[0] = -1; //這里采用-1做標(biāo)識while(j < plen -1){if(k == -1 || p[j] == p[k]){++k;++j;next[j] = k;}else{k = next[k];}}return next;} View Code

國際慣例貼上源代碼:

import java.util.Scanner;public class PatternString {public static int bruteForceStringMatch(String source, String pattern){int slen = source.length();int plen = pattern.length();char[] s = source.toCharArray();char[] p = pattern.toCharArray();int i = 0;int j = 0;if(slen < plen)return -1; //如果主串長度小于模式串,直接返回-1,匹配失敗else{while(i < slen && j < plen) {if(s[i] == p[j]) //如果i,j位置上的字符匹配成功就繼續(xù)向后匹配 {++i;++j;}else{i = i - (j -1); //i回溯到主串上一次開始匹配下一個位置的地方j = 0; //j重置,模式串從開始再次進(jìn)行匹配 }}if(j == plen) //匹配成功return i - j;elsereturn -1; //匹配失敗 }}public static int kmpStringMatch(String source, String pattern){int i = 0;int j = 0;char[] s = source.toCharArray();char[] p = pattern.toCharArray();int slen = s.length;int plen = p.length;int[] next = getNext(p);while(i < slen && j < plen){if(j == -1 || s[i] == p[j]){++i;++j;}else{//如果j != -1且當(dāng)前字符匹配失敗,則令i不變,//j = next[j],即讓pattern模式串右移j - next[j]個單位j = next[j];}}if(j == plen)return i - j;elsereturn -1;}private static int[] getNext(char[] p){/*** 已知next[j] = k, 利用遞歸的思想求出next[j+1]的值* 1.如果p[j] = p[k],則next[j+1] = next[k] + 1;* 2.如果p[j] != p[k],則令k = next[k],如果此時p[j] == p[k],則next[j+1] = k+1* 如果不相等,則繼續(xù)遞歸前綴索引,令k=next[k],繼續(xù)判斷,直至k=-1(即k=next[0])或者p[j]=p[k]為止*/int plen = p.length;int[] next = new int[plen];int k = -1;int j = 0;next[0] = -1; //這里采用-1做標(biāo)識while(j < plen -1){if(k == -1 || p[j] == p[k]){++k;++j;next[j] = k;}else{k = next[k];}}System.out.println("next函數(shù)值:");for(int ii = 0;ii<next.length;ii++){System.out.print(next[ii]+ " ");}System.out.println();return next;}public static void main(String[] args) {Scanner sc = new Scanner(System.in);String a = sc.nextLine();String b = sc.nextLine();System.out.println(bruteForceStringMatch(a, b));System.out.println(kmpStringMatch(a, b));}} View Code

轉(zhuǎn)載于:https://www.cnblogs.com/jiaohanhan/p/6654874.html

總結(jié)

以上是生活随笔為你收集整理的字符串的模式匹配(Java实现)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。