复习—KMP算法
对于KMP算法的学习,在寒假时我还是搞不太明白,但几个月之后,对于它的理解又更近了一步。
首先是对于子串的自我匹配,求一个fail数组,fail[i]对于字符串SS的前ii个字符构成的子串,既是它的后缀又是它的前缀的字符串中(包括他),最长的长度记作fail[i]。
举个例子,abcdabc中fail[7]的值就是3。当我们失配的时候,就直接跳到fail[i]所指的值上,这样效率就提升很大。
同理,子串和模式串匹配也是这个套路。对于KMP算法的讲解,建议去bilibili上有一个印度人的视频讲的还比较清楚。
代码
#include<bits/stdc++.h> using namespace std; const int maxn=1e7+7; int fail[maxn],show[maxn]; char s1[maxn],s2[maxn]; int ans; int len1,len2; int j; void getfail(){ fail[1]=0; for(int i=2;i<=len2;i++){ while(j!=0&&s2[i]!=s2[j+1]) j=fail[j]; if(s2[i]==s2[j+1]) j++; fail[i]=j; } } void kmp(){ j=0; for(int i=1;i<=len1;i++){ while(j!=0&&s1[i]!=s2[j+1]) j=fail[j]; if(s1[i]==s2[j+1]) j++;//母串不动,子串自己动 if(j==len2){ ans++; show[ans]=i-len2+1;//求子串出现的位置 } } } int main(){ scanf("%s%s",s1+1,s2+1); len1=strlen(s1+1); len2=strlen(s2+1); getfail(); kmp(); for(int i=1;i<=ans;i++){ printf("%d\n",show[i]); } for(int i=1;i<=len2;i++){ printf("%d ",fail[i]); } return 0; }