kmp算法核心思想就是求next数组:那我们就来谈谈next数组
普通next:
void getnext(){
int j,k;
j=0;
k=-1;
Next[0]=-1;
int le = strlen(a);
while(j<le){
if(k==-1||t[j]==t[k]) Next[++j]=++k;you
else k=Next[k];
}
}
对于普通next,那就有优化的next,但是普通next也有它独特的地方,利用普通next,我们可以求出主串中有多少子串。
int kmpcount(){
int ans=0;
int i=0;
int j=0;
if(l1==1&&l2==1){//一处优化
if(s[0]==t[0])
return 1;
else return 0;
}
getnext();
for(i=0;i<l1;i++){
while(j>0&&s[i]!=t[j]) j=Next[j];
if(s[i]==t[j]) j++;
if(j==l2){
ans++;
j=Next[j];
}
}
return ans;
}
注意:在全局变量最好不要用next,可能会有冲突,用Next就没有了。
优化next
void getnext(){
int le=strlen(a);
Next[0]=-1;
int k=-1;
int j=0;
while(j<le-1){
if(k==-1||a[j]==a[k]){
j++;
k++;
if(a[j]!=a[k]) Next[j]=k;
else Next[j]=Next[k];
}
else k=Next[k];
}
return;
}
这个优化过的next数组,比普通next匹配更快,但这个不能去求主串中子串的个数。
int KMP()
{
int i=0;
int j=0;
int lens=strlen(s);
int lenp=strlen(p);
while(i<lens&&j<lenp){
//如果j=-1(表示第一次开始或者重新开始匹配),即失配于首字符
if(j==-1||s[i]==p[j]){
j++;
i++;
}
else{
//如果j!+-1,或者当前匹配失败 ,则
j=Next[j]; // i不变,j=next[j]
}
}
if(j==lenp)
return 1;//匹配成功
else
return 0;
}
ios::sync_with_stdio(0);
cin.tie(0);
这段代码放在主函数开头,有利解除对cin和cout的安全保护,加快速度,使之接近scanf和printf。