课本知识和竞赛用的还是略微有些差别:
比如next数组的求法,虽说原理上一样(最长公共前后缀),但是表示起来还是有一点点区别:
比如: abcabaa
按照最长公共前后缀的求法:
先得到:0001211
之后去掉最后一位,得到000121,再把第一位赋值为-1;即-1000121,这个就是我们一般做oj题用的所谓next数组;
但是按照课本的求法:你会发现结果却是0111232,
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAX=500;
int Next[MAX];
int nextval[MAX];
typedef struct{
char ch[MAX+1];
int length;
}SString;
int Index_KMP(SString S,SString T,int pos){
int i=pos;
int j=1;
while(i<=S.length&&j<=T.length){
if(j==0||S.ch[i]==T.ch[j]){
++i;++j;
}
else
j=Next[j];
}
if(j>T.length) return i-T.length;
else return 0;
}
void get_next(SString T,int Next[]){
int i=1;
Next[1]=0;
int j=0;
while(i<T.length){
if(j==0||T.ch[i]==T.ch[j]){
++i;++j;Next[i]=j;
}
else j=Next[j];
}
}
void get_nextval(SString T,int nextval[]){
int i=1;
nextval[1]=0;
int j=0;
while(i<T.length){
if(j==0||T.ch[i]==T.ch[j]){
++i;++j;
if(T.ch[i]!=T.ch[j]){
nextval[i]=j;
}
else nextval[i]=nextval[j];
}
else j=nextval[j];
}
}
int main(){
SString s,t;
cout<<"请输入主串s"<<endl;
cin>>s.ch+1;
s.length=strlen(s.ch+1);
cout<<"请输入子串t"<<endl;
cin>>t.ch+1;
t.length=strlen(t.ch+1);
int m=s.length;
int n=t.length;
cout<<"主串为"<<endl;
for(int i=1;i<=m;i++){
cout<<s.ch[i];
}
cout<<endl;
cout<<"子串为"<<endl;
for(int i=1;i<=n;i++){
cout<<t.ch[i];
}
cout<<endl;
get_next(t,Next);
cout<<"Next数组为"<<endl;
for(int i=1;i<=n;i++){
cout<<Next[i];
}
cout<<endl;
get_nextval(t,nextval);
cout<<"nextval数组为"<<endl;
for(int i=1;i<=n;i++){
cout<<nextval[i];
}
cout<<endl;
int val=Index_KMP(s,t,1);
if(val) cout<<"在"<<val<<"位置匹配成功"<<endl;
else cout<<"匹配失败"<<endl;
return 0;
}
╮(╯_╰)╭,原始的才是最经典的。