KMP算法的优化与推进---nextval数组的推导

一、nextval的提出
在一些特殊的模式串我们发现KMP算法还是有缺陷的。
比如,S = “aaaabcde”,T = “aaaaax”
它的next数组值是 next=[012345]。因此当i=5、j=5时,此时的b与a不相等。如下图的1所示。因为j=next[5]=4。所以j回退到4的位置,但是此时主串的b与模式串的a还是不相等。于是j=next[4]=3,j回退到3的位置,发现依然是不相等的。所以j继续回退,直到主串中的a与模式串中的a相等。如图中的6所示:
在这里插入图片描述

所以我们发现图中的2345的步骤是多余的,因为T串中的第2、3、4、5
位置的字符都与首位的a不相等,所以我们可以用next[1]的值去取代后面字符的next[j]的值。这就是nextval的数组的出现。
二、nextval数组值推导
1、T =“ababaaaba”
根据我们常规的推导方法可以得出次模式串的next数组是

next[-1,0,0,1,2,3,1,1,2]

但这个next数组的推导的前提是模式串的下标是从0开始的,但为了方便nextval数组的推导,我们让模式串的下标从1开始,所以它的next数组就成为了

next[0,1,1,2,3,4,2,2,3]

只需要给下标从0开始的next的数组的每个值加1就可以

此模式串nextval数组的推导如下所示:
我们先给出next数组和nextval数组的值,如下图所示:
在这里插入图片描述
推导过程如下:
(1)当j=1时,nextval[1] = 0;
(2)当j=2时,我们可以看到next[2]=1。所以当j=2的时候我们就去找下标为1的字母。我们发现下标为1的字母时a,它与此时的b不相等。所以j=2时,它维持它的next数组的值,nextval[2]=next[2]=1;
(3)当j=3时,我们可以看到next[3]的值为1。所以当j=3的时候我们就去找下标为1的字母。我们发现下标为1的字母为a,它与此时的a相等,我们只需取next[1]的值就可以。所以当j=3时,它就等于next[1]的值,nextval[3]=next[1]=0;
(4)当j=4时,我们可以看到next[4]的值为2。所以当j=4的时候我们就去找下标为2的字母。我们发现下标为2的字母为b,它与此时的b相等,我们只需取next[2]的值就可以。所以当j=4时,它就等于next[2]的值,nextval[4]=next[2]=1;
(5)当j=5时,我们可以看到next[5]的值为3。所以当j=5的时候我们就去找下标为3的字母。我们发现下标为3的字母为a,它与此时的a相等,我们只需取next[3]的值就可以。所以当j=5时,它就等于next[3]的值,nextval[5]=next[3]=0;
(6)当j=6时,我们可以看到next[6]=4。所以当j=6的时候我们就去找下标为4的字母。我们发现下标为4的字母时b,它与此时的a不相等。所以j=6时,它维持它的next数组的值,nextval[6]=next[6]=4;
(7)当j=7时,我们可以看到next[7]=2。所以当j=7的时候我们就去找下标为2的字母。我们发现下标为2的字母时b,它与此时的a不相等。所以j=7时,它维持它的next数组的值,nextval[7]=next[7]=2;
(8)当j=8时,我们可以看到next[8]的值为2。所以当j=8的时候我们就去找下标为2的字母。我们发现下标为2的字母为b,它与此时的b相等,我们只需取next[2]的值就可以。所以当j=8时,它就等于next[2]的值,nextval[8]=next[2]=1;
(9)当j=9时,我们可以看到next[9]的值为3。所以当j=9的时候我们就去找下标为3的字母。我们发现下标为3的字母为a,它与此时的a相等,我们只需取next[3]的值就可以。所以当j=9时,它就等于next[3]的值,nextval[9]=next[3]=0;
三、代码实现
我们只需要在得到next的代码上加上几句代码就行了(next的实现的代码详见上篇博客)

void getNextval (char* t,int nextval[])
{
	int len = strlen(t) ;
    int j=1;
    int k=0;
    if (len == 0)
	{
		return;
	}
	nextval[1] = 0;
	if (len > 1)
	{
		nextval[1] = 1;
	}
	while(j〈len-1)
	{
		if (k == 0 || t[k] == t[j])//所有的匹配都已完成,没有任何最大的前缀和最大后缀相等
		{
			next[j+1]=k+1;
			j++;
			k++ ;
			if(t[k] != t[j])
			{
			nextval[j] = k;
			}
			else
			{
			nextval[j] = nexyval[j];
			}
			
		}
		else
		{
			k = nextval[k];
		}
	}
}

以上就是KMP算法的改进,重点核心也就是在next的数组的基础上求nextval的值。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值