const int manx=1e5;
int next[maxn],nextval[maxn];//nextval是kmp算法优化后的数组
char str1[maxn],str2[maxn];//str1表示的是主串str2表示的是次串
void getnext()
{
next[0]=next[1]=0;
int len=strlen(str2);
/*我们每次都对当前i位置的字符和当前位如果失配后要转移到的位置上的字符进行比较
(数组里面存的值)
*/
for(int i=1;i<len;i++){/
int j=next[i];
while(str2[i]!=str2[j]&&j) j=next[j];//如果当前位置i的字符和失配之后转移到的位置j对应的字符,就继续转移
next[i+1]=str2[i]==str2[j]?j+1:0;//如果当前位置i的字符和j是字符是相同的,那就在j+1就是当前i位置如果失配后要转移到的地方
}
}
void getnextval()//优化的next数组,会避免AAAAA这种字符串使kmp退化
{
next[0]=next[1]=0;
nextval[0]=nextval[1]=0;
int len=strlen(str2);
for(int i=1;i<len;i++){
int j=next[i];
while(str2[i]!=str2[j]&&j) j=next[j];
nextval[i+1]=next[i+1]=str2[i]==str2[j]?j+1:0;
//对next数组进行优化,将优化后的next数组存在nextval里面
//如果下一个位置i+1(我们每次都是在i的位置上推i+1处的next值)等于要转移到的位置对应的字符。
//那就直接 nextval[i+1]=nextval[j+1]
//相当于省去了i+1处失配后,先跳到j+1比较,再跳到next【j+1】比较。
//因为j+1处的字符是等于i+1处的,如果i+1处的字符匹配失败,j+1处的字符一定会匹配失败
if(str2[i+1]==str2[j+1]) nextval[i+1]=nextval[j+1];
}
}
void kmp()
{
getnext();//也可以是getnextval(),那之后该函数里面的数组就应该是nextval,而不是next。
int len1=strlen(str1),len2=strlen(str2);
for(int i=0;i<len1;i++){
if(j&&str1[i]!=str2[j]) j=next[j];//如果匹配不成功,我们当然是要用到我们的next数组了
if(str1[i]==str2[j]) j++;
if(j==len2){
//这里是匹配成功要做的操作 、
//如果只是返回第一个出现的位置 可以直接 return i-len2+1;
//如果只是记录子串出现的个数 可以直接 ans++;然后就不需要其他操作了
}
}
}