例题 洛谷P3375 KMP模板
/*
KMP算法
1.最长前缀后缀
2.基于公共最长前缀后缀进行匹配
失配时,模式字符串向右移动位数:已匹配字符数-失配字符上一位字符所对应的最长前缀后缀位数
3.next数组
next数组的求法就是最大长度表全部往右移动一位,然后最左边的那个值赋值为-1就可以了
4.通过代码来递推计算next数组
5.next数组的优化
6.完整的kpm算法
*/
#include<iostream>
#include<string>
#include<vector>
#include<cstring>
using namespace std;
#define MAXN 1000009
int nex[MAXN];
string s, p;
int slen,plen;
vector<int>ans;
void getNext() {
int t;
nex[0] = -1;
for(int i=1;i<plen;i++){
t=nex[i-1];
while(p[t+1]!=p[i]&&t>=0){
t=nex[t]; //不断回溯,找到匹配点
}
if(p[t+1]==p[i])
nex[i]=t+1;
else
nex[i]=-1;
}
}
void kmp() {
int i=0,j=0;
while(i<slen){
if(s[i]==p[j]){
i++;
j++;
if(j==plen){
ans.push_back(i-j+1);
j=nex[j-1]+1;
}
}else{
if(j==0)
i++;
else{
j=nex[j-1]+1;
}
}
}
}
int main(){
cin>>s>>p;
slen=s.size();
plen=p.size();
getNext();
kmp();
int len=ans.size();
for(int i=0;i<len;i++){
cout<<ans[i]<<endl;
}
for(int j=0;j<plen;j++){
cout<<nex[j]+1<<" ";
}
cout<<endl;
}