1. 程式人生 > >KMP模式匹配演算法中next,nextval的分別實現

KMP模式匹配演算法中next,nextval的分別實現

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;
}