KMP算法及前缀数组NEXT代码实现
KMP算法
KMP算法由D.E.Knuth,J.H.Morris和V.R.Pratt提出,主要解决字符串匹配问题。即在文本串中寻找模式串是否存在。相比朴素模式的字符串比较KMP的时间复杂度大约在O(m+n),这主要得益于KMP在对每次失配之后,都不会从头重新开始枚举,而是根据我已经得知的数据,从某个“特定的位置”开始匹配;而对于模式串的每一位,都有唯一的“特定变化位置”,这个在失配之后的“特定变化位置”可以帮助我们利用已有的数据不用从头匹配,从而节约时间。
前缀数组NEXT
KMP算法的核心就在于前缀数组的构建,这里主要针对短小灵活的模式串构建前缀数组,前缀数组就是用来存储模式串中每一位的“特定的位置”,这个“特定的位置”实际上就是到当前位置的最长公共前后缀长度。
例如:
A A B A B A A F
0 1 0 1 0 1 2 0
实现代码:
void GetNext()//Next数组:Next数组,Next[i]表示0~i的字符串的最长相同前后缀的长度。
{
plen=strlen(p);
Next[0]=-1;
int k=-1;
int j=0;
while(j < plen){
if(k==-1||p[j]==p[k]){
k++;
j++;
Next[j]=k;
}
else k=Next[k];
}
}
代码
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int Next[1000000+5];
char p[1000000+5],t[1000000+5];
int plen,tlen;
void GetNext()//Next数组:Next数组,Next[i]表示0~i的字符串的最长相同前后缀的长度。
{
plen=strlen(p);
Next[0]=-1;
int k=-1;
int j=0;
while(j < plen){
if(k==-1||p[j]==p[k]){
k++;
j++;
Next[j]=k;
}
else k=Next[k];
}
}
void FindStr()
{
int i=0,j=0;
tlen = strlen(t);
while(i<tlen)
{
if(j==-1||t[i]==p[j])
{
if(j==strlen(p)-1)
{
printf("%d\n",i-j+1);
j=Next[j];
}
j++;
i++;
}
else j=Next[j];
}
}
int main()
{
scanf("%s",&t);
scanf("%s",&p);
GetNext();
FindStr();
for (int i = 1; i <= plen; i ++ )
printf("%d ",Next[i]);
puts("");
return 0;
}