通常我們想在乙個字串中匹配乙個子字串,會遍歷字串,對於每乙個字元,都遍歷子字串進行匹配,這樣時間複雜度為o(nm);
使用kmp演算法只需先進行乙個o(m)的預處理(生成next陣列),就能將搜尋的時間複雜度降低至o(n+m)。下面講一講kmp演算法的實現原理。
對於abcdeabd...和abcdeabc,當匹配至最後一位是發現不匹配,之前的abcdeab都是匹配的,這段字串包含有哪些資訊?即相同的字首ab和字尾ab,這樣,下一次移動子字串可以直接移至下乙個ab進行匹配,移動了7-2位(7是匹配的字串長度,2是匹配的字首字尾長度),而next陣列就是表示匹配字首字尾長度的陣列。
搜尋詞 a b c d a b d
next 0 0 0 0 1 2 0
"a"的字首和字尾都為空集,共有元素的長度為0;
"ab"的字首為[a],字尾為[b],共有元素的長度為0;
"abc"的字首為[a, ab],字尾為[bc, c],共有元素的長度0;
"abcd"的字首為[a, ab, abc],字尾為[bcd, cd, d],共有元素的長度為0;
"abcda"的字首為[a, ab, abc, abcd],字尾為[bcda, cda, da, a],共有元素為"a",長度為1;
"abcdab"的字首為[a, ab, abc, abcd, abcda],字尾為[bcdab, cdab, dab, ab, b],共有元素為"ab",長度為2;
"abcdabd"的字首為[a, ab, abc, abcd, abcda, abcdab],字尾為[bcdabd, cdabd, dabd, abd, bd, d],共有元素的長度為0。
理解了kmp演算法的基本原理,下一步就是要獲得字串f每乙個位置的最大公共長度。這個最大公共長度在演算法導論裡面被記為next陣列。在這裡要注意一點,
next
陣列表示的是長度,下標從
1開始;但是在遍歷原字串時,下標還是從
0開始。假設我們現在已經求得next[1]、next[2]、……next[i],分別表示長度為1到i的字串的字首和字尾最大公共長度,現在要求next[i+1]。由上圖我們可以看到,如果位置i和位置next[i]處的兩個字元相同(下標從零開始),則next[i+1]等於next[i]加1。如果兩個位置的字元不相同,我們可以將長度為next[i]的字串繼續分割,獲得其最大公共長度next[next[i]],然後再和位置i的字元比較。這是因為長度為next[i]字首和字尾都可以分割成上部的構造,如果位置next[next[i]]和位置i的字元相同,則next[i+1]就等於next[next[i]]加1。如果不相等,就可以繼續分割長度為next[next[i]]的字串,直到字串長度為0為止。
public class test
while (tmp < s.length()&&s.charat(tmp) == str.charat(count))
}i += count - next[count];
} system.out.println("not match");
} public static int getnext(string str)
return next;
}}
Java實現KMP演算法
對於查詢字元子串在父字串中出現的位置,我們可以使用kmp演算法。kmp演算法的實現原理是使子串向右滑盡可能的遠,這就涉及到求滑動距離的陣列next.next陣列中每個元素求解的公式是 private static void kmpnext int next,string str 這裡需要附加說明的是...
KMP演算法(java實現)
kmp演算法是由donald kunth vaughan pratt james h.morris三個人發明的,是一種複雜度很小的匹配字串的演算法。給定兩個字串str和match,長度分別為n和m。實現乙個演算法,如果字串str中含有子串match,則返回match在str中的開始位置,不含有則返回...
KMP 演算法 java實現
在網上找到的 執行出來的模式值和資料裡根據定義計算出來的值不一樣,沒有找到合適的,於是手寫了乙個。模式值定義 1 next 0 1 意義 任何串的第乙個字元的模式值規定為 1。2 next j 1 意義 模式串t中下標為j的字元,如果與首字元相同,且j的前面的1 k個字元與開頭的1 k個字元不等 或...