【模板】kmp以及扩展kmp

来源:互联网 发布:薛之谦的男装淘宝店 编辑:程序博客网 时间:2024/06/06 00:25

kmp算法:
最佳博客: http://www.cnblogs.com/dolphin0520/archive/2011/08/24/2151846.html  
这里面kmp算法讲的比较详细,我主要在这写下自己的kmp模板以及需要注意的地方。

void getnext(int t){int i=0,j=-1;while(i!=t)   {    if(j==-1||a[i]==a[j])    {     i++;     j++;     next[i]=j;    }    else j=next[j];   }} 

这是kmp算法中求next数组的算法,需要注意的是这个next是指的下一位的比较,而不是本位的比较。
例如:       aabaac中,c的next位是2,也就是说若在c处比较不相等,那么直接回溯到b处再进行比较
                 012345
                 -101012

扩展kmp:
可以在网上看看刘雅琼的ppt。
扩展kmp是求两个数组最大相同前缀数目的节约时间的算法,其时间是线性的,也就是a+b类的,而不是a*b。
扩展kmp模板:

#include<stdio.h>#include<string.h>char a[110010],b[110010];int next[110010],ex[110010];void getnext(int t)                //这个子函数是求扩展kmp中模板数组的next数组,和kmp算法中的next数组完全不同。{                                          //扩展kmp算法中next数组是指从这一位开始最大的与全字符串相同的前缀。 int i,k,L,j,p; next[0]=t; for(i=0;i<t;i++)  if(b[i]!=b[i+1]) break;         //在getnext函数中,i是循环节的标记符,p是最大相同前缀的最长长度,  next[1]=i;                            // 例如:acabcaca,当循环到第二个a时,p为3,当循环到第三个a时,p为8. k=1;p=k+next[k]-1; for(i=2;i<t;i++) {  L=next[i-k];  if(i+L<=p) next[i]=L;  else  {   j=p-i+1;   if(j<0) j=0;   while(i+j<t&&b[i+j]==b[j]) j++;    //注意添加限制条件   next[i]=j;k=i;p=k+next[k]-1;  } }}void getex(int t)                            //ex数组是指a串与b串最大相同前缀。{ int i,k,p,L,j; for(i=0;i<t;i++)  if(a[i]!=b[i]) break; k=0;ex[0]=i; for(i=1;i<t;i++) {  p=k+ex[k]-1;  if(p<0) p=0;  L=next[i-k];  if(i+L<=p) next[i]=L;  else  {   j=p-i+1;   if(j<0) j=0;   while(i+j<t&&a[i+j]==b[j]) j++;   ex[i]=j;k=j;  } }}int main(){ int len,i,j,max; while(scanf("%s",a)!=EOF) {  getchar();  len=strlen(a);  j=len-1;  max=0;  for(i=0;i<len;i++)  {   b[j]=a[i];   j--;  }  for(i=0;i<len;i++)   printf("%c ",b[i]);  printf("\n");  getnext(len);  for(i=0;i<len;i++)   printf("%d ",next[i]);  printf("\n");  getex(len);  for(i=0;i<len;i++)   printf("%d ",ex[i]);  printf("\n");  /*for(i=0;i<len;i++)   if(max<ex[i]) max=ex[i];  printf("%d\n",max);*/ }} 



 

原创粉丝点击