一個長度爲n的字符串T(文本串),和長度爲m的字符串(模板串),在字符串T中尋找字符串匹配點,樸素的算法就是二重循環暴力尋找,這樣的時間複雜度爲O(n*m),而現在要介紹的kmp算法時間複雜度O(n+m),這個時間複雜度已經達到理論的上屆了,因爲至少所有的字符都需要遍歷
1.算法的本質
kmp算法是利用模板串自身的特性判斷出失配後該走向哪裏
比如字符串abbaaba在匹配到最後一個的時候發現不匹配了,這個時候前面6個文本字符的信息abbaab的信息就可以加以利用前綴ab和後綴ab相同,所以移動至少要移動4位,而爲了記錄每次失配後應該怎麼走需要在引進一個數組f
void getfail(char *p,int *f)
{
int m=strlen(p);
f[0]=0;
f[1]=0;
for(int i=1;i<m;i++)
{
int j=f[i];
while(j&&p[i]!=p[j]) j=f[j];//利用前面的信息進行遞推
f[i+1]=p[i]==p[j]?j+1:0;//若p[i]==p[j],則失配時到j+1再比較,此時已經保證前j個已經匹配
}
}
void find(char *T,char *P,int *f)
{
int n=strlen(T),m=strlen(P);
getfail(P,f);//計算f數組
int j=0;
for(int i=0;i<n;i++)
{
while(j&&T[i]!=p[j]) j=f[j];//順着失配邊走
if(T[i]==p[j]) j++;//模板串後移
if(j==m) printf("%d\n",i-m+1);
}
}
順着失配邊走已經保證前面一定是匹配的,只要當前能夠匹配,模板串向右移