KMP算法初步

来源:互联网 发布:php base64解码 乱码 编辑:程序博客网 时间:2024/05/16 23:59

今天本来是要做动归的,结果做到了几道AC自动机上的动归。用到了KMP,当时我就蛋疼了。

其实这个东西很早之前就有接触过,但是实际上一次也没有真正写过- -。

所以写那些动归之前,先接触接触KMP算法吧。

------------------------------------------------------------------------------------------------

其实本质思想并不难(弄懂了几乎没什么东西是难的),是利用了当前的部分匹配去继续匹配未完成的匹配。

比如ababc在bababcddea中的匹配吧,我们首先做出ababc的next函数(失败指针),如何做呢?自己匹配自己。

我们可以从这个过程中算出,ababc每一个位置的失败指针。


这里要解释一下失败指针的定义,比如说

      next[i]表示pattern字符串的前next[i]-1位与pattern字符串往前数的next[i]-1位完全匹配且第next[i]位必定不匹配。

      next[i]为-1则没法找到满足条件的匹配。

于是在接下来的匹配中,如果一旦出现失配,我们无需像简单匹配中那样将两个字符串上的指针归位,而是继续

利用已经完成的匹配,如果出现已经完成的匹配无法继续利用的情况(即next[pos]==-1),则继续匹配下一个位置。


有人说KMP的预处理next函数和匹配部分非常相近,个人写起来还是觉得有些区别的,虽然思想本质是一样的。

------------------------------------------------------------------------------------------------

#include<iostream>#include<cstdio>#include<cstring> using namespace std;int n,ans;int next[10010];char aim[10010],str[1000010];void Pre(){int j,k;j=0; k=-1; next[0]=-1;while(aim[j]!='\0'){if(k!=-1&&aim[k]!=aim[j]) k=next[k];++j; ++k;if(aim[k]==aim[j]) next[j]=next[k];else next[j]=k;}}void KMP(){int i,j;i=j=0;while(str[i]!='\0'){if(str[i]==aim[j]){i++; j++;if(aim[j]=='\0') ans++;}else{if(next[j]!=-1) j=next[j];else{j=0; i++;}}}}int main(){freopen("3461.in","r",stdin);scanf("%d",&n);while(n--){ans=0;scanf("%s",aim);scanf("%s",str);Pre();KMP();printf("%d\n",ans);}return 0;}

0 0