[KMP算法]有问题!网上这份代码是可以AC,但并不全对!!!!

今天我在学习KMP算法的时候,看到了一份令我十分钟意的代码。(当然这份是我自己打的,但大体不变)

void get_next(string s)
{
	next[0]=-1;
	int j=0,k=-1;
	while(j<s.size())
	if(k==-1||s[k]==s[j]) next[++j]=++k;
	else 				  k=next[k];
}

这是份你在网络上可以搜到的大致的构造next数组的代码。
他在那一整份代码中实际上是没有问题的。
你会发现,作为模式串的最后一个字符,它会默认继承前一个字符的next,不论它是否满足要求。但在主串与模式串的匹配过程中,最后一个字符的next没有影响,因为不管是否匹配都要移动到前面的某一位,不行可以接着再移。

比如说模式串为abab,这样的next数组为{-1,0,1,2}。
但在构建next数组时,我们对最后一个字符并没有做处理。在if语句中,我们对某位的字符匹配,操作的却是后一位字符的next。很奇怪吧,但是没有问题,因为最后一位不重要。与主串不匹配,就不取它嘛,无论如何依然向前移动嘛。(可以自己去推推)
比如说主串与模式串匹配过程如下:

int work_KMP(string s,string p)
{//不要在意,这里的目的是统计匹配的子串数,不是返回位置。
	int i,j,res;i=j=res=0;
	while(i<s.size())
	{
		if(j==-1||s[i]==p[j]) ++i,++j;  else j=next[j];
		if(j==p.size())       ++res,         j=next[j];
	}
	return res;
}

于是乎,当我们最后一位字符改变时,比如abad,它的next数组依旧为{-1,0,1,2}!!当我做另外一题时,便发现这个写法不仅不清楚,而且存在这个致命的错误。要改的话,不如打另一种版本的。
这与KMP算法的思想是不符的。

我开始也挺蒙圈的,搞懂(可能还没有完全搞懂,欢迎指正)了以后,我选择一本通高效进阶的这个代码:

inline void pre()
{
	p[1]=0;
	for(int i=1,j=0;i<m;++i)
	{
		while(j>0&&b[j+1]!=b[i+1])
  		    j=p[j];
		if(b[j+1]==b[i+1])
		    ++j;
		p[i+1]=j;
	}
}

或者这个大佬的代码:KMP算法 详解+模板 - cervusky

void getnx()
{
    nx[1]=0;
    for(int i=2,j=1;i<=n;)
    {
        nx[i]=j;
        while(j&&s1[j]!=s1[i])j=nx[j];
        j++,i++;
    }
}

这就十分的清晰明了,且十分符合KMP算法的思想。(当然了,我觉得高效进阶里的代码都着实不太行,但这里姑且还清楚)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值