KMP
KMP 算法是一种改进的字符串匹配算法,由 D.E.Knuth,J.H.Morris 和 V.R.Pratt 提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称 KMP 算法)。KMP 算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个 next() 函数实现,函数本身包含了模式串的局部匹配信息。KMP 算法的时间复杂度 \(O(m+n)\)。—— 百度百科。
举个栗子:
模式串:abcabc
文本串:abcabdababcabc
匹配到第 \(6\) 位时失配,将模式串的第 \(1,2\) 位移动到第 \(4,5\) 位。
然后就是前缀与后缀。
对于一个模式串,如果 后一个位置 不行,我们可以找到一个与当前匹配好的串的 后缀相同的前缀串的位置。—— a_grain 大佬。
大致如此(其实是我不会。
贴个代码吧 qwq
//by a_grain
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int la,lb,j,i,fail[N];
char a[N],b[N];
void read(int &x){
x=0;int f=1;
char c=getchar();
while(!isdigit(c))(c=='-'?f=-1:1),c=getchar();
while(isdigit(c))x=(x<<1)+(x<<3)+(c^48),c=getchar();
x*=f;
}
inline void write(int x){
if(x<0)x=-x,putchar('-');
if(x>9)write(x/10);
putchar(x%10+48);
}
void kmp(){
int j=0;
for(int i=2;i<=la;i++){
while(j&&a[j+1]!=a[i])j=fail[j];
if(a[j+1]==a[i])j++;
fail[i]=j;
}
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin>>(b+1)>>(a+1);
la=strlen(a+1);lb=strlen(b+1);
kmp();
j=0;
for(i=1;i<=lb;i++){
while(j&&a[j+1]!=b[i])j=fail[j];
if(a[j+1]==b[i])j++;
if(j==la)
cout<<i-la+1<<'\n';
}
for(i=1;i<=la;i++)
cout<<fail[i]<<' ';
return 0;
}
浙公网安备 33010602011771号