扩展KMP算法

来源:互联网 发布:我知谁掌管明天 作者 编辑:程序博客网 时间:2024/06/08 00:22

参考:点击打开链接

第一种情况:k+len<P

如下图所示:

  

上图中,S[k+1,k+len]=T[0,len-1],然后S[k+len+1]一定不等于T[len],因为如果它们相等,则有S[k+1,k+len+1]=T[k+po+1,k+po+len+1]=T[0,len],那么next[k+po+1]=len+1,这和next数组的定义不符(next[i]表示T[i,m-1]和T的最长公共前缀长度),所以在这种情况下,不用进行任何匹配,就知道extend[k+1]=len。

第二种情况: k+len>=P

如下图:


上图中,S[p+1]之后的字符都是未知的,也就是还未进行过匹配的字符串,所以在这种情况下,就要从S[P+1]和T[P-k+1]开始一一匹配,直到发生失配为止,当匹配完成后,如果得到的extend[k+1]+(k+1)大于P则要更新未知P和po。

/*扩展KMP*/#include <iostream>#include <algorithm>#include <cstring>#include <cstdio>#include <stack>#include <cmath>#include <queue>#include <map>using namespace std;#define N 100012char s[N];char pattern[N];int next[N],extend[N];void getnext(){    int start=0,p=0;    int j=0,len=strlen(pattern);    next[j]=len;    for(int i=1;i<len;i++) {        if(i>=p||i+next[i-start]>=p){            if(i>=p)                p=i;            while(p<len&&pattern[p]==pattern[p-i])                p++;            next[i]=p-i;            start=i;        }        else            next[i]=next[i-start];    }    return ;}int main(){    scanf("%s%s",s,pattern);    getnext();    int len=strlen(s);    int len2=strlen(pattern);    int start=0,p=0;    for(int i=0;i<len;i++) {        if(i>=p||i+next[i-start]>=p) {            if(i>=p)                p=i;            while(p<len&&p-i<len2&&s[p]==pattern[p-i])                p++;            extend[i]=p-i;            start=i;        }        else            extend[i]=next[i-start];    }    for(int i=0;i<len;i++)        cout<<extend[i]<<" ";    cout<<endl;return 0;}