KMP

KMP及其应用

Nick_zheng 2 分钟阅读

$KMP$ 及其应用

特别声明: 以下仅为个人直观理解, 并不都正确严谨


$KMP$, 一种求(字符串)匹配问题的算法, 但不仅局限于此, 其中蕴含的前缀函数的思想可以在许多字符串甚至推广到一些看似毫无关联的题目中 qaq.

这里先贴出模板(附加个人的直观理解, 不是正规解释, 仅供娱乐 qaq)

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+10;
string a,b;
int kmp[N];//next数组, 最长前后缀长度数组
signed main()
{
	cin>>a;
	cin>>b;
	int lena=a.size();
	int lenb=b.size();
	a=" "+a;
	b=" "+b;//下标1开头
	int j=0;//子串匹配过的长度
	for(int i=2;i<=lenb;i++)//next[1]=0(规定)
	{
		while(j&&b[i]!=b[j+1])//确保j合法, 且失配
		{
			j=kmp[j];//跳走继续匹配
		}
		if(b[i]==b[j+1])//如果可以匹配
		{
			j++;//则往后移动
		}
		kmp[i]=j;//此时的j就是next[i]的值
	}
	j=0;//清零
	int cnt=0;
	for(int i=1;i<=lena;i++)//直接复制即可, 改几处, 注意这次要从1开始
	{
		while(j&&a[i]!=b[j+1])
		{
			j=kmp[j];
		}
		if(a[i]==b[j+1])
		{
			j++;
		}
		if(j==lenb)//子串全部匹配成功
		{
			printf("%lld\n",i-lenb+1);//i-j+1也可, 求出的位置(此时i为末尾, 要减去j-1)
			//处理, 可以做标记/dp等
			j=kmp[j];//跳到下一个位置继续匹配
		}
	}
	for(int i=1;i<=lenb;i++)
	{
		printf("%lld ",kmp[i]);//按要求输出
	}
	printf("\n");
	return 0;
}

好的, 以上就是 $KMP$ 的基础作用 qaq.

...