KMP

时间:2021-08-20
本文章向大家介绍KMP,主要包括KMP使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

oi-wiki

应用:在字符串中查找子串,求循环节长度等。

字符串匹配:

暴力思想,枚举每一个每一个文本串元素,然后从这一位开始不断向后比较,每次比较失败之后都要从头开始重新比对,复杂度易被卡成 \(O(nm)\)

而对于 KMP 算法,在每次失配之后,不会从头重新开始枚举,而是根据已得知的数据,从失配后的特定位置开始匹配,使复杂度优化至 \(O(n+m)\).

适配后的特定位置:失配数组(见这里

lg模板

code:

#include<bits/stdc++.h>
using namespace std;

const int N=1e6+10;
char a[N],b[N];int k[N],la,lb;//k数组即为失配数组

int main()
{
	scanf("%s%s",a+1,b+1);
	la=strlen(a+1),lb=strlen(b+1);
	int j=0;
	for(int i=2;i<=lb;i++)
	{
		while(j/*如果回跳到第一个字符就不用再回跳了*/&&b[j+1]!=b[i]) j=k[j];
		if(b[j+1]==b[i]) j++;//通过自己匹配自己来得出每一个点的kmp值 
		k[i]=j;//i+1失配后跳的地方
	}j=0;
	for(int i=1;i<=la;i++)
	{
		while(j&&b[j+1]!=a[i]) j=k[j];//如果失配 ,那么就不断向回跳,直到可以继续匹配 
		if(b[j+1]==a[i]) j++;//如果匹配成功,那么对应的模式串位置加1
		if(j==lb) printf("%d\n",i-lb+1),j=k[j];
	}
	for(int i=1;i<=lb;i++) printf("%d ",k[i]);
	return 0;
}

循环节长度: len-kmp[len]

code:

void KMP()
{
    for(int i=1;i<len;i++)
    {
        while(j>0&&a[j+1]!=a[i+1]) j=kmp[j];
        j=a[j+1]==a[i+1]?j+1:j;
        kmp[i+1]=j;
    }
    cout<<len-kmp[len];
}

\(\texttt{End.}\)

原文地址:https://www.cnblogs.com/Juruo-lxgw/p/KMP.html