標籤:KMP演算法 Java 字串匹配
一、什麼是KMP演算法?
維基百科的解釋是:在電腦科學中,Knuth-Morris-Pratt字串尋找演算法(簡稱為KMP演算法)可在一個主文本字串S內尋找一個詞W的出現位置。此演算法通過運用對這個詞在不匹配時本身就包含足夠的資訊來確定下一個匹配將在哪裡開始,從而避免重新檢查先前已經匹配過的字元。
二、字串的首碼與尾碼
首碼:字串除了最後一個字元的全部頭部組合;
尾碼:字串處理第一個字元的全部頭部組合;例如
三、字串部分匹配表
"部分匹配"的實質是,有時候,字串頭部和尾部會有重複。比如,"ABCDAB"之中有兩個"AB",那麼它的"部分匹配值"就是2("AB"的長度)。搜尋字詞移動的時候,第一個"AB"向後移動4位(字串長度-部分匹配值),就可以來到第二個"AB"的位置。所以我們需要找到一個字串中每一個子串的匹配值,即找到字串的部分匹配值表,這樣的話我們在下面匹配字串的過程中就可以根據匹配表來進行跳躍了,而不必一個一個字元往後移,這就是關鍵所在。
四、KMP演算法實現過程
簡單來說,KMP演算法就是根據上面我們已經得到的部分匹配表來判斷:匹配過程中發現子串的某個字元與待匹配串不對應時,子串應該往後移幾位。
移動的位元 = 已經匹配成功的串的總長度 - 已經匹配成功的串的部分匹配值
有些繞,舉個栗子,假如我要判斷字串"BBC ABCDAB ABCDABCDABDE"中是否含有串“ABCDABD”,我把前面這個長串叫做待匹配串,把“ABCDABD”叫做子串(有可能叫法不對但明白就行)。
匹配的過程為:
將字串"BBC ABCDAB ABCDABCDABDE"的第一個字元與搜尋字詞"ABCDABD"的第一個字元,進行比較。因為B與A不匹配,所以搜尋字詞後移一位。直到有匹配的字元位置,如下:
圖中當匹配到D時發現不對應了,此時:
已經匹配成功的串為:ABCDAB
已經匹配成功的串的總長度:6
已經匹配成功的串的部分匹配值 :2
移動的位元 = 6 - 2,直接將子串往後移動4位,繼續開始匹配
一樣的道理,此時已經匹配成功的串為AB,移動的位元 = 2 - 0,往後移動2位繼續匹配
沒有匹配成功的串,往後移一位
已經匹配成功的串為:ABCDAB,ABCDAB的部分匹配值為2,移動的位元 = 6 - 2,往後移動4位
此時子串所有的字元都被匹配,搜尋完成。
五、Java實現
public class KmpAlgo { //尋找待匹配串的部分匹配值,放在next數組中 static void getNext(String pattern,int[] next){ int j = 0; int k = -1; next[0] = -1; int len = pattern.length(); while(j < len-1){ if(k == -1 || pattern.charAt(j) == pattern.charAt(j)){ j++; k++; next[j] = k; }else{ k = next[k]; } } } static int kmp(String s,String pattern){ int i = 0; int j = 0; int slen = s.length(); int plen = pattern.length(); int[] next = new int[plen]; getNext(pattern,next); while(i < slen && j < plen){ if(s.charAt(i) == pattern.charAt(j)){ i++; j++; }else if(next[j] == -1){ i++; j = 0; }else{ j = next[j]; } if(j == plen){ return i-j; } } return -1; } /** *@param */ public static void main(String[] args){ String str = "ABCDABDEYGF"; String pat = "ABCDABD"; //KmpAlgo.kmp(str, pat); System.out.println(KmpAlgo.kmp(str, pat)); }}
字串匹配(KMP)演算法及Java實現