一、引言
- KMP又稱模式匹配算法,能夠在線性時間內判定字符串A[1~N]是是否爲B[1 ~ M]的子串,並求出A在B中各次出現的位置。
二、基本含義
- next數組:next[i] 代表A中以i結尾的非前綴子串(非前綴子串的意思就是不能和A完全相等的後綴子串) 與 A的前綴能夠匹配的最大長度。
- 當不存在這樣的前綴串時,顯然next[i] = 0, 故next[1] = 0 (因爲第一個字符前面沒有字符串且第一個字符不是非前綴子串)
- 我們可以讓A對B進行匹配,求出一個數組p。p[i]代表以i結尾的子串 與 A的前綴能夠匹配的最大長度。 當p[i] = n(A的長度)代表匹配此位置成功。
三、next數組的求解
1. 樸素的求解next數組
- 假定A串爲 abababbc
2. 優化求解next數組過程
void getNext() { //n串A串的長度
for (int i = 2, j = 0; i <= n; i++) { //求解next[i]
while (j && A[i] != A[j + 1]) j = ne[j]; //這時候找到一個符合的位置 A[i] == A[j + 1] 那麼就停止了。
if (A[i] == A[j + 1]) j++; //這時候有2種情況,j==0:代表前面的串都不滿足。 否則那麼next[i] = j + 1。
ne[i] = j; // 求解出ne[i] 。
}
}
三、kmp算法
- 這時候我們與串B匹配的過程和求解next的過程大同小異。
void kmp() {
for (int i = 1, j = 0; i <= m; i++) {
while (j && B[i] != A[j + 1]) j = ne[j];
if (B[i] == A[j + 1]) j++; //在前面已經匹配的長度的基礎上加1
p[i] = j; //代表B串以i結尾的子串與 A的前綴的最大匹配長度 匹配串爲B[i - j + 1, i]
//if (j == n) {//匹配成功 }
}
}
四、其他應用
- 最小循環節