这个题就是并查集的模板题
一开始我想按照我在《大话数据结构》上的来写,但是上面就是一个建立next数组,没有之后的判断,而且上面的next数组不是以下标0开始的,而是以下标1开始的,像这样,
int getnext(char ch[],int length,int next){
next[1]=0;
int i=1,j=0;
while(i<length){
if(j==0||ch[i]==ch[j]){
i++;
j++;
if(ch[i]!=ch[j])
next[i]=j;
else
next[i]=next[j];
}
}
else
j=next[j];
}
而且我想用string类型来写这个题(就是单纯的懒),这样的话我干脆就不用这个递推的方式来写了,用循环来找next数组也不是不可以
思路:我们先要创建好next数组,也就是在marknext函数中去建立,然后去KMP函数中寻找
思路是不难,关键就是在与理解如何创建next数组和KMP寻找中
我们在创建next数组的时候,如果j为0时候,要让j等于next[j-1]也就是0(这一步我们单独写也可以),又或者是当brr[j]!=brr[i]的时候,就要让j等于你匹配失败前的next数组的值,让子串(也就是模式串)进行回溯,如果没有进行while循环的话,也就代表着我们此时主串和子串的相同最大先后缀+1,因为是相同的,就让j++让next[i]对应的值增加
然后是KMP函数里面的判断,为了方便我还是用的for循环的,当j不等于0并且brr[j]!=arr[i]的时候,我们就要进行j的回溯,回溯多少就看next[j-1]的值是多少,如果它们相等,就让j++,进行下一个字符的判断,也就是让主串和子串都向后移动一个位置,最后,要是在主串中找到了子串,我们就打印出是第几个就好了,但是要注意,因为第几个是以1开始的,而我们的数组是从0开始的,所以说需要i+1,而且长度的计算也就从1开始的,也要+1,
#include<bits/stdc++.h>
using namespace std;
#define maxn 1000005
string arr,brr;
int len1,len2;
int nextttt[maxn];
void marknext(){
nextttt[0]=0;
int j=0;
for(int i=1;i<len2;i++){
while(j&&brr[j]!=brr[i])
j=nextttt[j-1];
if(brr[j]==brr[i])
j++;
nextttt[i]=j;
}
}
void KMP(){
int j=0;
for(int i=0;i<len1;i++){
while(j&&brr[j]!=arr[i])
j=nextttt[j-1];
if(brr[j]==arr[i])
j++;
if(j==len2)
printf("%d\n",i+1-len2+1);
}
}
int main(){
cin>>arr;
cin>>brr;
len1=arr.length();
len2=brr.length();
marknext();
KMP();
for(int i=0;i<len2;i++)
cout<<nextttt[i]<<" ";
}