KMP算法的Next数组的优化

Next数组是KMP算法的一个难点,而求Next数组时最难的不过就是k = Next[k] 这一行了。首先要理解的是,k是在模式串当前角标之前已经匹配的前缀后缀的长度。
Next[i] 表示在角标i 之前已经匹配的前缀后缀的长度。
如果s[j] == s[k], 说明当前前缀和后缀可以匹配到长度为k的相同字符;
如果s[j] != s[k], 就说明了当前前缀后缀无法匹配到长度为k+1的相同字符,这个时候需要找有没有更短的可能,所以就有了k = Next[k]。

这么说肯定不好理解,还是通过图片来理解。
在这里插入图片描述
到最后一位的时候, 发现无法匹配了,也就是找不到K+1了,这时候需要回退一下,看看能不能找到比k长度小的相同字符串,也就执行了k = Next[k];也就是到了下图的位置。
在这里插入图片描述
你会发现这里不正好是上上次匹配的地方嘛,也就证明了第六位不能匹配第十位,那就往回退一下,看一下能不能委屈求全一下,找一个短一点的前缀来匹配第十位。

**

优化Next数组

**
接下来进入我们今天的正题,对于下面的图片:
在这里插入图片描述
当到达D后不再匹配,按照以前的KMP算法,是变成了下面的图片:
在这里插入图片描述
这个时候D又是与B失配,原因很简单,p[Next[4]] = p[1] = b, 而接下来的匹配就是p[1]和D进行匹配,那必然是失配的。我们应该避免出现p[j] = p[Next[j]];,如果出现了,那么下一步必然失配。
可能有人就想到了,那我就再KMP里面修改代码,如果p[Next[j]] = p[j], 那就继续递归寻找。
接下来给出优化Next数组的代码

#include <iostream>

using namespace std;

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

下面给出Next数组和优化后的Next数组的图片:
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值