KMP模板

打ACM的时候又碰到了kmp,就翻了翻以前的博客
怎么说呢,感觉以前写的好烂啊,全是一些感性的理解,没有任何严格的证明,而且代码不是很简洁。
所以这里推荐还是看书吧,比如李煜东的《算法竞赛进阶指南》就讲的很好,而且代码写的很精炼,我觉得如果我写这篇文章的话,也只不过是把书上的话复述一遍,所以这里我就贴一个代码吧。


kmp推荐字符串从1开始标号,因为当f[i]=0的时候表示在模板串的当前位置,没有任何一个前缀能和对应的后缀匹配上,但如果从0开始标号的话就会引起歧义。
题目就是洛谷的kmp板子

#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 1e6 + 5;

char s[maxn], s2[maxn];

int f[maxn];
void kmp_init(char* s)
{
	int n = strlen(s + 1); f[1] = 0;
	for(int i = 2, j = 0; i <= n; ++i)
	{
		while(j && s[j + 1] != s[i]) j = f[j];
		if(s[j + 1] == s[i]) ++j;
		f[i] = j;
	}
}
void kmp(char* t, char* p, int* f)
{
	int n = strlen(t + 1), m = strlen(p + 1);
	for(int i = 1, j = 0; i <= n; ++i)
	{
		while(j && (j == m || t[i] != p[j + 1])) j = f[j];
		if(t[i] == p[j + 1]) ++j;
		if(j == m) printf("%d
", i - j + 1);
	}
}

int main()
{
	scanf("%s%s", s + 1, s2 + 1);
	kmp_init(s2), kmp(s, s2, f);
	int m = strlen(s2 + 1);
	for(int i = 1; i <= m; ++i) printf("%d ", f[i]); puts("");
	return 0;
}
原文地址:https://www.cnblogs.com/mrclr/p/14216422.html