KMP算法通过寻找最大前后缀来实现效率的提高,最基础的用法是寻找模式串B在主串A中的位置(出现次数)
KMP模板需要两个函数:pre()找到模式串的next数组;
kmp()实现算法主体;
代码:
#include<bits/stdc++.h>
#define MAXN 10007 //字符串最大长度
using namespace std;
char A[MAXN],B[MAXN];
int P[MAXN],la,lb;
void pre()
{
p[1]=0;
int j=0;
for(int i=1;i<lb;i++) //每次循环计算的是p[i+1],由于p[1]=0,i从1开始
{
while(j>0&&B[j+1]!=B[i+1]) j=P[j];
if(B[j+1]==B[i+1]) j++;
P[i+1]=j; //记录算出的值
}
}
int kmp()
{
int ans=0,j=0;
for(int i=0;i<la;i++) //每次比对A[i+1]和B[j+1],所以i,j初始值都为0
{
while(j>0&&B[j+1]!=A[i+1]) j=P[j];
if(B[j+1]==A[i+1]) j++;
if(j==m) //找到,执行特定操作
{
cout<<i-m+2<<endl;
j=P[j];
}
}
return ans;
}
int main()
{
cin>>A+1; //输入从A[1]开始
cin>>B+1;
m=strlen(B+1); //记录长度从B[1]开始,从B开始长度是0
n=strlen(A+1);
pre();
kmp();
for(int i=1;i<=m;i++)
{
cout<<P[i];
if(i!=m) cout<<' ';
}
}
需要注意的细节
两个字符串都是从下标为1的位置开始的,在输入和调用strlen()函数求长度时需要注意
pre()中j=0,循环从i=1开始到i<lb结束 ; kmp()中j=0,循环从i=0开始到i<la结束
pre()和kmp()循环中通用部分是
while(j>0&&下一位不相等)j=p[j];
if(下一位相等)j++;
差异部分:pre()循环中第三句是p[i+1]=j //记录下一位的next值
kmp()循环第三句是if(j==lb){ 找到字串,执行特定操作 } //找到子串