KMP模式匹配演算法中next,nextval的分別實現
阿新 • • 發佈:2019-02-18
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; }