时间复杂度O(n+m)
pmt[i],s从0到i的前缀等于后缀的字串的最大长度,但小于s本身长度。pmt[0]=0;
下面代码找出s中p的所有位置,下标从1开始。
#include <bits/stdc++.h>
int pmt[5000009];
void get_pmt(std::string &str){
int i,j;
for(i=1,j=0;i<(int)str.size();i++){
while(j&&str[i]!=str[j]){
j=pmt[j-1];
}
if(str[i]==str[j]){
j++;
}
pmt[i]=j;
}
return ;
}
void kmp(std::string &s,std::string &p){
int i,j;
for(i=0,j=0;i<(int)s.size();i++){
while(j&&s[i]!=p[j]){
j=pmt[j-1];
}
if(s[i]==p[j]){
j++;
}
if(j==(int)p.size()){
std::cout<<i-j+2<<std::endl;//1-index
j=pmt[j-1];
}
}
return ;
}
int main (){
std::string s;
std::string p;
std::cin>>s;
std::cin>>p;
get_pmt(p);
kmp(s,p);
int i;
for(i=0;i<(int)p.size();i++){
if(i!=0){
std::cout<<" "<<pmt[i];
}else{
std::cout<<pmt[i];
}
}
std::cout<<std::endl;
return 0;
}