KMP
应用:在字符串中查找子串,求循环节长度等。
字符串匹配:
暴力思想,枚举每一个每一个文本串元素,然后从这一位开始不断向后比较,每次比较失败之后都要从头开始重新比对,复杂度易被卡成 \(O(nm)\) 。
而对于 KMP 算法,在每次失配之后,不会从头重新开始枚举,而是根据已得知的数据,从失配后的特定位置开始匹配,使复杂度优化至 \(O(n+m)\).
适配后的特定位置:失配数组(见这里)
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.}\)

浙公网安备 33010602011771号