kmp算法总结
kmp算法总结
kmp算法可以以 \(O(n+m)\) 的超低复杂度来实现两个字符串的匹配功能。
我们先来定义一下 \(kmp_i\) 的意思是从 \(i\) 开始如果不能匹配的话,要跳会到哪里。
举个例子:
abcabdabcc
0001201230
abcabcabc
000123456
这个kmp有一个性质就是 \(kmp_i\) 表示 ss[1~i] 的前缀和后缀相等的情况下的最长长度。
然后我们在匹配是如果有失衡(也就是不匹配)的话,直接根据kmp往后跳就行。
很多情况下,不用跳到开头就可以接下去,所以可以大幅减小复杂度。
首先先预处理一下:
for(int i=2;i<=len2;i++){
while(j&&ss[i]!=ss[j+1]){//此处判断j是否为0的原因在于,
j=kmp[j];//如果失配 ,那么就不断向回跳,直到可以继续匹配
}
if(ss[j+1]==ss[i]){
j++;///果匹配成功,那么对应的模式串位置++
}
kmp[i]=j;
}
然后再做:
for(int i=1;i<=len1;i++){//如果失配 ,那么就不断向回跳,直到可以继续匹配
while(j&&s[i]!=ss[j+1]){
j=kmp[j];
}
if(s[i]==ss[j+1]){
j++;
}
if(j==len2){
cout<<i-len2+1<<endl;
j=kmp[j];
}
}
code:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
string s,ss;
ll len1,len2,kmp[2000000],j;
int main(){
cin>>s>>ss;
len1=s.size();
len2=ss.size();
s=' '+s;
ss=' '+ss;
for(int i=2;i<=len2;i++){
while(j&&ss[i]!=ss[j+1]){
j=kmp[j];
}
if(ss[j+1]==ss[i]){
j++;
}
kmp[i]=j;
}
j=0;
for(int i=1;i<=len1;i++){
while(j&&s[i]!=ss[j+1]){
j=kmp[j];
}
if(s[i]==ss[j+1]){
j++;
}
if(j==len2){
cout<<i-len2+1<<endl;
j=kmp[j];
}
}
for(int i=1;i<=len2;i++){
cout<<kmp[i]<<" ";
}
}
可以自由转载

浙公网安备 33010602011771号