kmp优化正确性证明

邓俊辉老师的课上给出了一种普遍的kmp算法优化,但是没有给出这种优化的正确性证明。或许这种正确性是显而易见的,但这里还是研究了一下这个算法的正确性问题。

int* buildNext(char* P) {
	int n = strlen(P);
	int* next = new int[n];
	int i = 0, j = next[0] = -1;

	while (i < n - 1) {
		if (j < 0 || P[i] == P[j]) {
			++i;
			++j;
			//原算法
			next[i] = j;
			//优化算法
			newNext[i] = P[i] != P[j] ? j : newNext[j];
		}
		else
			//原算法
			j = next[j];
			//优化算法
			j = newNext[j];
	}

	return next;
}

显然,算法的优化核心即在于对P[i]P[j]相等时的处理,亦即,若目标串T[k]P[i]不可匹配,则T[k]必然与P[j]不可匹配,回溯至j显然是一种远远不够的回溯,按照原算法的运行逻辑,则会递归j = next[j]直至T[k] = P[i] != P[j]。很自然的,我们可以通过递推改进这个递归公式,这个的正确性是显然的,通过保证前面满足条件来保证后面均满足条件。
优化算法的实际变动不仅于此,由于改变的next数组的含义,那么显然,我们需要保证j = newNext[j]仍能发挥原先的作用,才可保证j的取值满足newNext数组的正确性。显然,在这个算法中,newNext数组表示的是在P[0, j)中,P[0, t) = P[j-t, j) && P[t] != P[j] 情况下t的最大值。因此,若P[i] != P[j],则可令k = j,递归k = next[k]直至P[j] != P[k],此时P[i]P[j]方有相同的可能。此回溯与newNext数组的含义不谋而合,因此我们可以使用j = newNext[j]来代替原算法的j = next[j],算法的功能仍得以保存。
因此,整个优化算法过程中,j的变化仍与原算法相同,仅有些微小的变化,而这些微小的变化仅仅是“跳步”迭代而已,这保证了next数组与newNext数组在P[i] != P[j]情况下取值相同,算法的正确性得以保证。

这个算法我脑子里有个坎一直过不去,老觉得这有问题那有问题,想通了就非常简单,没想到写出来能这么恶心,写了好久仍然只写出了个大概意思,各位看官将就着看吧,有哪里没有写清楚的可以评论探讨。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
KMP算法正确性证明可以通过数学归纳法来进行。下面是证明的步骤: 1. 基本情况:当模式串为空时,任何字符串都可以匹配成功,所以KMP算法是正确的。 2. 假设在长度为n的文本串T中,已经找到了一个位置i,使得T[i-n+1...i]与模式串P[1...n]匹配。我们要证明,如果T[i+1]与P[n+1]不匹配,那么存在一个位置j,使得T[j-n+1...j]与P[1...n]匹配,并且j > i。 3. 根据KMP算法的思想,当T[i+1]与P[n+1]不匹配时,我们需要找到一个位置k,使得T[i-k+1...i]与P[1...k]匹配,并且k < n。这是因为,如果T[i-k+1...i]与P[1...k]匹配,那么T[i-k+1...i]与P[1...n]的前k个字符也是匹配的。 4. 假设在位置i-k+1到i之间存在一个位置m,使得T[m-k+1...m]与P[1...k]匹配,并且m > i。根据KMP算法的定义,我们可以得到π[k] = m-k+1。 5. 现在我们要证明,如果T[i+1]与P[n+1]不匹配,那么存在一个位置j,使得T[j-n+1...j]与P[1...n]匹配,并且j > i。根据KMP算法的定义,我们有π[n] = j-n+1。 6. 根据假设,我们知道T[i-k+1...i]与P[1...k]匹配,所以T[i-k+1...i]与P[1...n]的前k个字符也是匹配的。根据π[k] = m-k+1,我们可以得到T[m-k+1...m]与P[1...n]的前k个字符也是匹配的。 7. 因为T[m-k+1...m]与P[1...n]的前k个字符是匹配的,所以T[m-k+1...m]与P[1...n]也是匹配的。根据π[n] = j-n+1,我们可以得到T[j-n+1...j]与P[1...n]也是匹配的。 8. 综上所述,如果T[i+1]与P[n+1]不匹配,那么存在一个位置j,使得T[j-n+1...j]与P[1...n]匹配,并且j > i。 根据上述证明,我们可以得出结论:如果在文本串T中找到了一个位置i,使得T[i-n+1...i]与模式串P[1...n]匹配,那么KMP算法可以正确地找到所有的匹配位置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值