KMP

luogu P3375 【模板】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;
}