KMP算法思想
KMP算法是D.E.Knuth,J.H.Morris和V.R.Pratt共同提出的,簡稱爲KMP算法。
該算法較BF算法有較大的改進:每當一趟匹配過程中出現字符不相等時,主串指示器 i 不用回溯,而是利用已經得到的“部分匹配”結果,將模式串向右“滑動”儘可能遠的一段距離後,與 i 對齊,繼續進行比較。
KMP算法過程示例
當 i = 3,j = 3時失配。
此時按照BF算法,將子串P右移一位:
按照KMP算法,儘可能的多移幾位,i 的位置不變,使得模式P中的某個位置繼續與 i 進行比較:
發現當 i = 7,j = 5時失配:
模式P繼續向右滑動,進行第三次匹配:
此時匹配完成。
確定next[ ] 函數
因此我們需要對模板s[ ]進行預處理:
以 i 爲終點的後綴 = 從1開始的前綴,且長度最長
即next[ i ] = j :
s[ 1…j ]這一段 = s[ i-j+1 … i ] 這一段
C++代碼實現
注:s[ ]下標從1開始,p[ ]下標從0開始,所以s[ i ] 對應的是p[ j+1 ]
#include<iostream>
#define N 10010
#define M 100010
using namespace std;
int main()
{
int n, m;
char s[M], p[N];
int ne[N];
cin >> n >> p+1 >> m >> s+1;
for(int i = 2, j = 0; i <= n; i++) //求出 next[]
{
while(j && p[i] != p[j+1])
j = ne[j];
if(p[i] == p[j+1])
j++;
ne[i] = j;
}
for(int i = 1, j = 0; i <= m; i++) //KMP算法
{
while(j && s[i] != p[j+1])
j = ne[j];
if(s[i] == p[j+1])
j++;
if(j == n)
{
printf("%d ", i-n);
j = ne[j];
}
}
return 0;
}