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;
}
posted @ 2021-03-23 22:03  Treasure_lee  阅读(123)  评论(0编辑  收藏  举报