Ax
AAy
AAAz
AAAAdm
求 next[mi] 。 mi代表m在數組中的index。 zi,yi,xi亦如此。
如圖z和d不相等,則需要比較y和d,
AAy
AAz
next[zi] = yi = k
y=array[k]
如果y和d相同, 則next[mi] = k+1
如果y和d不相等,則需要比較d和x
Ax
Ay
next[yi] = xi = k1
x=array[k1]
如果x和d相同, 則next[mi]= k1+1
如果x和d不相等,
next[xi] =0
d是否等於array[0] 又回到起點。。。 array[0] = d
next[mi] = 1;
否則 k = next(0) = -1
next[mi] = 0
next[zi] = yi
next[yi] 是[xi]
next[xi] 是 0
next[0] 是-1
即d和x,y,z,array[0]都不相等時需要比較m和array[0]的大小。 再次回到起點。哈哈哈
可以自行進行驗證:
ab
A=空集。
abacd
A={a}
Ab
Acd
abababcd
A = {ab}
Aa
AAa
AAAcd
最基礎的代數法則。
ababababdm
A={ab}
a
Aa
AAa
AAAa
AAAAdm
public class KMP { public static void main(String[] args) { int index = Solution.kmp("fsdfdasfffsd","ababababdm") ; System.out.println(index); } } class Solution { // KMP算法,返回匹配的首字符下標,否則返回-1 public static int kmp(String s, String t) { int m = s.length(), n = t.length(); int[] next = new int[n]; getNext(t, next); int i = 0, j = 0; while (i < m && j < n) { if (j == -1 || s.charAt(i) == t.charAt(j)) { i++; j++; } else j = next[j]; } if (j >= n) return i - n; else return -1; } // 計算next數組 private static void getNext(String t, int[] next) { int j = 0, k = -1, n = t.length(); next[0] = -1; while (j < n - 1) { if (k == -1 || t.charAt(j) == t.charAt(k)) { // System.out.printf("j===%d,k===%d%n",j,k); j++; k++; next[j] = k; } else { System.out.printf("j===%d,k===%d%n",j,k); k = next[k]; } } } }
在這裏能發現一個很有意思的事情,當j相同時,k的排列爲一個等差數列,步長爲A的長度。
kmp算法適用於p串有重複字串的場景,當p串沒有重複的字串時和暴力解法一樣。
改進版的KMP算法。
public class KMP { public static void main(String[] args) { int index = Solution.kmp("fsdfdasfffsd", "abcabdabcabababababababababdm"); System.out.println(index); } } class Solution { // KMP算法,返回匹配的首字符下標,否則返回-1 public static int kmp(String s, String t) { int m = s.length(), n = t.length(); int[] next = new int[n]; getNext(t, next); int i = 0, j = 0; while (i < m && j < n) { if (j == -1 || s.charAt(i) == t.charAt(j)) { i++; j++; } else { j = next[j]; } } if (j >= n) { return i - n; } else { return -1; } } // 計算next數組 private static void getNext(String t, int[] next) { int j = 0, k = -1, n = t.length(); next[0] = -1; while (j < n - 1) { if (k == -1 || t.charAt(j) == t.charAt(k)) { // System.out.printf("j===%d,k===%d%n",j,k); j++; k++; if (t.charAt(j) == t.charAt(k)) { // 當兩個字符相等時要跳過 next[j] = next[k]; } else { next[j] = k; } } else { System.out.printf("j===%d,k===%d%n", j, k); k = next[k]; } } } }