Kmp--P3375 【模板】KMP字符串匹配

 

把已经给出的串称为文本串,要在文本串中找的串称为模式串。特别地,前两位$(kmp[0],kmp[1])$为零。比如串$ABABAC$,它的$fail$应该为001230。
已知第$i$位的自动机$kmp[i]$,要求第$i+1$位的。设$j=kmp[i]$。$kmp[i]$一定在i前面,$kmp[i]$已经求好了。如果字符串的$i$和$j+1$位不同$(s2[i]≠s2[j+1])$,那么j不断地跳到自己的自动机$kmp[j]$,直到匹配上或$j=0$为止。如果匹配上,$f[i] = j+1$;否则如果还是$s2[i]≠s2[j+1]$,说明是$j=0$而不是匹配上了,那么$kmp[j] = 0$。

构建自动机:

 1  j=0;
 2     for (int i=2;i<=lb;i++){     
 3        while(j&&b[i]!=b[j+1])
 4        //此处判断j是否为0的原因在于,如果回跳到第一个字符就不 用再回跳了
 5        j=kmp[j];    
 6         //通过自己匹配自己来得出每一个点的kmp值 
 7        if(b[j+1]==b[i])j++;    
 8        kmp[i]=j;
 9         //i+1失配后应该如何跳 
10        }

我们已经对该子串构建了一个自动机,当两个字符串相比较,如果失配,即$s1[i]!=s2[j+1]$就跳回,此时一定两位匹配$(j!=0)$或从头开始$(j=0)$,之后再匹配下一位即可。

运行自动机:

 1   int j;
 2     j=0;//j可以看做表示当前已经匹配完的模式串的最后一位的位置 
 3     //也可以理解为j表示模式串匹配到第几位了 
 4     for(int i=1;i<=la;i++){
 5           while(j&&b[j+1]!=a[i])j=kmp[j];
 6           //如果失配 ,那么就不断向回跳,直到可以继续匹配 
 7           if (b[j+1]==a[i]) j++;
 8           //如果匹配成功,那么对应的模式串位置++ 
 9           if (j==lb) {
10           cout<<i-lb+1<<endl;
11           j=kmp[j];
12           //继续匹配 
13           }
14        }

 完整代码:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<cstring>
 5 using namespace std;
 6 #include<string>
 7 const int maxn = 1e6+10;
 8 int len1,len2,f[maxn];
 9 string s1,s2;
10 void fail() {
11     f[0] = f[1] = 0;
12     for(int i = 1; i < len2; i++) {
13         int j = f[i];
14         while(j && s2[i]!=s2[j]) j = f[j];
15         if(s2[i] == s2[j]) f[i+1] = j+1;
16         else f[i+1] = 0;
17     }
18 }
19 void kmp() {
20     int j = 0;
21     for(int i = 0; i < len1; i++) {
22         while(j && s1[i]!=s2[j])j = f[j];
23         if(s1[i] == s2[j])j++;
24         if(j == len2) {
25             printf("%d
",1+i-len2+1);
26             j = f[j];
27         }
28     }
29 }
30 
31 int main() {
32     cin>>s1>>s2;
33     len1 = s1.length();
34     len2 = s2.length();
35     fail();
36     kmp();
37     for(int i = 1; i <= len2; i++)
38         printf("%d ",f[i]);
39     return 0;
40 }
原文地址:https://www.cnblogs.com/very-beginning/p/12283569.html