贴一个B站讲解清晰的视频
再发个洛谷模板题
这次我真会写了!
里面有些下标和结构问题要牢记
#include<bits/stdc++.h>
#define int long long
#define md(arr) memset(arr,0,sizeof(arr));
using namespace std;
const int N=1e3+10;
vector<int> getNext(string p){
vector<int>next(p.size()+1);
next[0]=next[1]=0;
for(int i=1;i<p.size();i++){
//i是后缀要匹配下标
//j=next[i]是前缀要匹配下标
//next记录的长度j
//已经匹配好前缀字符串最后一个下标j-1
//现在要匹配的下标j-1+1=j
int j=next[i];
//已经匹配好的前后缀是相同的,在字串找前缀的前缀匹配后缀的后缀
//其实就是找前缀的最长前后缀长度
while(j and p[i]!=p[j])j=next[j];
//仅仅只剩一个需要匹配的前后缀字符
//next[i]指的是i个长度字符的最长公共前后缀
//for i 是指下标
if(p[j]==p[i])next[i+1]=j+1;
else next[i+1]=0;
}
return next;
}
void kmp(string s,string p){
vector<int>next=getNext(p);
int j=0;
for(int i=0;i<s.size();i++){
while(j and s[i]!=p[j])j=next[j];
if(s[i]==p[j])j++;
if(j==p.size()){
cout<<i+2-p.size()<<endl;
}
}
for(int i=1;i<=p.size();i++){
cout<<next[i]<<" ";
}cout<<endl;
return;
}
void work(){
string s,p;
cin>>s>>p;
kmp(s,p);
}
signed main (){
//freopen("C:\\Users\\Lenovo\\Desktop\\in.txt","r",stdin);
//freopen("C:\\Users\\Lenovo\\Desktop\\out.txt","w",stdout);
std::cin.tie(0);
std::ios::sync_with_stdio(false);
int Case=1;
//cin>>Case;
while(Case--){
work();
}
return 0;
}