zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    React Virtual Dom 与 Diff
    打造前端CI/CD工作流
    webpack-chain明细
    React项目中实现多语言支持
    【WPF】大量Canvas转换为本地图片遇到的问题
    【C#】【分享】 XX分钟学会C#
    【WPF】一些拖拽实现方法的总结(Window,UserControl)
    【WPF】 InkCanvas 书写毛笔效果
    js中this指向问题
    js原型浅谈理解
  • 原文地址:https://www.cnblogs.com/very-beginning/p/12283569.html
Copyright © 2011-2022 走看看