KMP模式匹配算法中next,nextval的分别实现

来源:互联网 发布:阿里云1m带宽下载速度 编辑:程序博客网 时间:2024/05/23 18:34

next数组定义:

对于这个定义,我的理解是从1~j-1中,前缀与后缀有n个相等,则next[j]=n+1。

例如:t="abcabaa"

当j=1时,next[1]=0。

当j=2时,从1~j-1,串为a,next[2]=1。

当j=3时,从1~j-1,串为ab,next[3]=1。

当j=4时,从1~j-1,串为abc,next[4]=1。

当j=5时,从1~j-1,串为abca,next[5]=2。

当j=6时,从1~j-1,串为abcab,next[6]=3。

当j=7时,从1~j-1,串为abcaba,next[7]=2。

nextval数组,即nextval的改进

他是在计算出next数组的同时,如果第i个字符与他next[i]所指的字符相等,则nextval[i]=nextval[next[i]]。否则,nextval[i]=next[i]。

例如:t="abcabaa"

当j=1时,next[1]=0,nextval[1]=0。

当j=2时,从1~j-1,串为a,next[2]=1,b!=a,nextval[2]=1。

当j=3时,从1~j-1,串为ab,next[3]=1,c!=a,nextval[3]=1。

当j=4时,从1~j-1,串为abc,next[4]=1,a==a,nextval[4]=0。

当j=5时,从1~j-1,串为abca,next[5]=2,b==b,nextval[5]=1。

当j=6时,从1~j-1,串为abcab,next[6]=3,a!=c,nextval[6]=3。

当j=7时,从1~j-1,串为abcaba,next[7]=2,a!=b,nextval[7]=2。

代码:

#include <iostream>#include <string>#include <cstdio>#include <cstring>using namespace std;void get_next(char *t,int *next){    int len=strlen(t+1);    int i=1,j=0;    next[i]=j;    while(i<len)    {        if(j==0||t[i]==t[j])//后缀的单个字符与前缀的单个字符        {            ++i;            ++j;            next[i]=j;        }        else            j=next[j];    }//    for(int k=1;k<=len;++k)//        cout<<next[k]<<" ";//    cout<<endl;    return;}void get_nextval(char *t,int *nextval){    int i=1,j=0;    nextval[1]=0;    int len=strlen(t+1);    while(i<len)    {        if(j==0||t[i]==t[j])        {            ++i;            ++j;            if(t[i]!=t[j])//若当前字符与前缀字符不相等                nextval[i]=j;//则当前的j为nextval在i位置的值(即next[i])            else//若当前字符与前缀字符相等                nextval[i]=nextval[j];//则将前缀字符的nextval的值赋值给nextval[i],即nextval[i]=next[next[i]];        }        else            j=nextval[j];    }//    for(int k=1;k<=len;k++)//        cout<<nextval[k]<<" ";//    cout<<endl;}//返回子串t在主串s中第pos个字母后的位置int kmp_next(char *s,char *t,int pos){    int next[105];    memset(next,0,sizeof(next));    get_next(t,next);    int i=pos;    int j=1;    int len_s=strlen(s+1);    int len_t=strlen(t+1);    while(i<=len_s&&j<=len_t)    {        if(j==0||s[i]==t[j])        {            ++i;            ++j;        }        else            j=next[j];    }    if(j>len_t)//表示t串匹配成功        return i-len_t;    else        return 0;}int kmp_nextval(char *s,char *t,int pos){    int nextval[105];    memset(nextval,0,sizeof(nextval));    get_nextval(t,nextval);    int i=pos;    int j=1;    int len_s=strlen(s+1);    int len_t=strlen(t+1);    while(i<=len_s&&j<=len_t)    {        if(j==0||s[i]==t[j])        {            ++i;            ++j;        }        else            j=nextval[j];    }    if(j>len_t)        return i-len_t;    else        return 0;}int main(){    char t[105],s[105];    int pos;    scanf("%s%s%d",s+1,t+1,&pos);    printf("%d\n",kmp_next(s,t,pos));    printf("%d\n",kmp_nextval(s,t,pos));    return 0;}