算法:KMP字符串匹配

0x01 暴力方法

很容易想到,字符串匹配可以把模式串在文本串上一个个匹配,但是太慢了。

0x02 前缀数组

在kmp算法中,前缀数组很重要,kmp[i]记录的是从模式串开头,截取长度为 \(i\) 的字串后,在该字串中,最长的公共前后缀长度
代码:

for(int i=2;i<=lb;i++){
	int j=kmp[i-1];
	while(j>0&&b[i]!=b[j+1])j=kmp[j];
	if(b[i]==b[j+1])j++;
	kmp[i]=j;
}

0x03 模式串匹配

按照前缀数组,一旦失配,模式串向前平移,直到最长前缀与最长后缀重合,大大节省时间复杂度。
代码:

#include<bits/stdc++.h>
using namespace std;
int la,lb;
char a[1000010];
char b[1000010];
int kmp[1000010];
int main(){
	scanf("%s%s",a+1,b+1);
	la=strlen(a+1);
	lb=strlen(b+1);
	for(int i=2;i<=lb;i++){
		int j=kmp[i-1];
		while(j>0&&b[i]!=b[j+1])j=kmp[j];
		if(b[i]==b[j+1])j++;
		kmp[i]=j;
	}
	int j=0;
	for(int i=1;i<=la;i++){
		while(j&&b[j+1]!=a[i])j=kmp[j];
		if(b[j+1]==a[i]){
			j++;
		}
		if(j==lb){
			printf("%d\n",i-lb+1);
			j=kmp[j];
		}
	}
	for(int i=1;i<=lb;i++){
		printf("%d ",kmp[i]);
	}
	return 0;
}
posted @ 2023-03-12 09:05  MornHus  阅读(25)  评论(0)    收藏  举报