next数组表示失配时,子串应该移向的位置
所以当时失配才考虑用next数组
通过移动子串p来寻找p在s串中出现的位置。
next[j]用来记录当s[i]和p[j]匹配不成功时,j从next[j]开始重新匹配
next数组表示当前字符之前的字符串中,最长相同前后缀长度。
kmp算法步骤:
当j=-1(p串从头开始匹配)或者s[i]和p[j]匹配时,{ i++; j++; }
当j!=-1且s[i]和p[j]不匹配时,{ i不变,j=next[j] } ;表示失配时,p串向右移动j-next[j]位
大神巨厉害详解
/*不要用next做数组名,与c++库函数next重复,会出CE*/
#include<bits/stdc++.h>
using namespace std;
int fff[150];
void getnextt(char p[])
{
int i,j,len;
i=0; j=-1; fff[0]=-1;//next初值赋为-1
len=strlen(p);
while(i<len-1)
{
if(j==-1||p[j]==p[i])//p[j]表前缀,p[i]表后缀(前后缀相同时)
{
++i;
++j;
if(p[i]!=p[j])//p[i]!=p[fff[i]],,匹配3.3.8
{
fff[i]=j;
}
else
fff[i]=fff[j];//如果相同,i的next返回相同前缀处的next
}
else//前后缀不相同时,j递归找长度变小的相同前缀.。。匹配3.3.4问题2
j=fff[j];
}
}
int kmp(char s[],char p[])
{
int i,j,len1,len2;
len1=strlen(s);
len2=strlen(p);
i=0;
j=0;
while(i<len1&&j<len2)
{
if(j==-1||s[i]==p[j])//j=-1表模板串从头开始开始匹配,s串从下一位开始继续匹配
{
i++;
j++;
}
else//匹配不相同,模板串从next[j]开始继续匹配,模板串向右移动j-next[j]位
j=fff[j];
}
if(j>=len2)
return i-len2;
else
return -1;
}
int main()
{
char s[150],p[150];
while(cin>>s>>p)
{
getnextt(p);
int ans=kmp(s,p);
cout<<ans<<endl;
}
return 0;
}