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