KMP及其扩展算法——源码、注释

来源:互联网 发布:cnc编程代码开头怎么编 编辑:程序博客网 时间:2024/05/20 00:17

关于KMP及其扩展的讲解有很多,可以自己百度下。

此文为个人的源码及整理的注释。

本人第一次写博文的菜鸟,将就着看吧。。。

#include <cstdio>#include <cstring>#include <iostream>using namespace std;char S[100],T[100];//S->母串,T->子串 int perfix[100],n=0,m=0,next[100],extend[100];//perfix[i]->T[1...perfix[i]-1]==T[i-perfix[i]+1...i-1]:T[1...perfix[i]]是 T[i-perfix[i]+1...i-1]的前缀,且perfix最大 //next[i]->T[1...next[i]]=T[i...m]:使T[1...next]==T[i...i+next-1]的最大next //extend[i]->T[1...extend[i]]=S[i...i+extend[i]-1]:使T[1...extend]==S[i...i+extend-1]的最大extend void _orgin()//base {int k=0;//T中当前位置的指针 perfix[1]=0;//对于首次出现的字符,perfix为0 for(int i=2;i<=m;i++){while(k>0 && T[k+1]!=T[i])k=perfix[k]; //若失配,则将指针调至perfix进行匹配 if(T[k+1]==T[i])k++;//若匹配成功,指针后移 perfix[i]=k;//若匹配失败,则k必定为0 }}void _KMP()//base{int k=0;//同上 for(int i=1;i<=n;i++){while(k>0 && T[k+1]!=S[i])k=perfix[k];//同上 if(T[k+1]==S[i])k++;//同上 if(k==m)printf("%d\n",i-m+1);//若k==m,即找到了T在S中的位置 }}void KMP_extend()//extend{next[1]=m;next[2]=m-1;for(int i=1;i<=m;i++)//预处理出next[2]的值 {if(T[i+1]!=T[i]){next[2]=i-1;break;}}int p,k=2,j,L;//p->当前最远匹配 ,使匹配最远的k for(int i=3;i<=m;i++)//此为T与自己的extend_kmp {p=k+next[k]-1;L=next[i-k+1];//由next定义(见变量申明下方的注释)->T[k...p]==T[1...p-k+1] ->T[i...p]==T[i-k+1...p-k+1] if(i+L<=p)//讨论i+L与p的关系 {next[i]=L;}else {j=p-i+1;//已知的长度 j=max(j,0);while(i+j<=m && T[i+j]==T[j+1])j++;//未知串检测匹配 next[i]=j;k=i;}}k=1;extend[1]=m;for(int i=1;i<=m;i++)//此为S与T的extend_kmp {if(S[i]!=T[i]){extend[1]=i-1;break;}}for(int i=2;i<=n;i++){p=k+extend[k]-1;L=next[i-k+1];if(i+L<=p){extend[i]=L;}else{j=p-i+1;j=max(j,0);while(i+j<=n && j<=m && S[i+j]==T[j+1])j++;extend[i]=j;k=i;}}for(int i=1;i<=m;i++)printf("next[%d]:%d\n",i,next[i]);for(int i=1;i<=n;i++)printf("extend[%d]:%d\n",i,extend[i]);}int main(){freopen("Kmp.in","r",stdin);freopen("Kmp.out","w",stdout);char a=getchar();while(a!='\n'){S[++n]=a;a=getchar();}a=getchar();while(a!='\n'){T[++m]=a;a=getchar();}_orgin();_KMP();KMP_extend();return 0;}


0 0