600秒速读 字符串匹配 KMP算法

基本思想

  • 将pattern和text从左到右进行比较,但与brute-force算法相比,KMP能更智能地转换pattern。
  • 当不匹配发生时,为了避免冗余的比较,我们能滑动pattern的位置最多是多少?
  • 假设问题是在一段Text(T)中找到Pattern(P)为abaaba的字符串,i 和 j 为 T 和 P 的 index,则如上答案,滑动pattern 最大的距离为 P[0…j-1] 的最大前缀同时也是 P[1…j-1] 的后缀。

在这里插入图片描述这里有一些理解上的难度,回过头来看在Text中找到Pattern为abaaba的情况。一个基本事实是当 T 中的 x 与 P 中的 a 不匹配时,已经知道前面五个字符 abaab 是匹配的。而KMP算法则利用已经比较过的字符串,把 pattern 往后继续滑,跳过已经比较过的位置。

KMP Failure Function

原理

  • KMP算法预处理pattern。
  • KMP算法的预处理部分,Failure function F(j) 被定义为 P[0…j] 的最大子前缀,同时也是
    P[1…j] 的后缀
    的 size
  • KMP算法将brute-force改变为,如果T和P在 P[j] != T[i] 处不匹配,则设 j ⇐ F(j-1),然后滑动。
  • 这咋整呢?借助部分匹配表(Partial Match Table)!
    在这里插入图片描述
    通俗来讲,即,移动位数 = 已匹配的字符数 - 对应的部分匹配值。这里 j 的最后一位对应的 a 不行,所以找到 j=5 时 F(j)=3,滑3位。
    在这里插入图片描述

部分匹配表(Partial Match Table)

这算是KMP算法中最核心的部分之一了。个人认为任何不涉及PMT的KMP算法介绍都是耍流氓。。。

首先,要了解两个概念:“前缀"和"后缀”。 "前缀"指除了最后一个字符以外,一个字符串的全部头部组合;"后缀"指除了第一个字符以外,一个字符串的全部尾部组合。(摘自阮一峰大佬)

以刚才的abaaba为例子,看一下前缀(prefix),后缀(suffix),最长子串(max-substring),最长子串长度(len-max-substring)

prefixsuffixmax-sublen-maxsub
anullnullnull0
ababnull0
abaa,abba,ba1
abaaa,ab,ababaa,aa,aa1
abaaba,ab,aba,abbabaab,aab,ab,bab2
abaabaa,ab,aba,abaa,abaabbaaba,aaba,aba,ba,aaba3

在这里插入图片描述
岂不美哉!
有了PMT表,可以往后延伸到所谓的Next表。

next表

Next 表是由 PMT 表得到的,做到就是將 PMT 表中的每一個值向后移动 1 位,第一位賦值為 -1。(摘自知乎–小撸伴读)

patternabaaba
PMT001123
Next-100112

在这里插入图片描述而这Next表的作用就是刚才讲的:KMP算法将brute-force改变为,如果T和P在 P[j] != T[i] 处不匹配,则设 j ⇐ F(j-1),然后滑动。

伪代码

Algorithm KMPMatch(T, P)
F ⇐ failureFunction(P)
i ⇐ 0
j ⇐ 0
while i < length(T)
	if T[i] = P[j] then
		if j = length(P) - 1 then
			return i - j { match }
		else
			i ⇐ i + 1
			j ⇐ j + 1
	else
		if j > 0 then
			j ⇐ F[j - 1]
		else
			i ⇐ i + 1
return -1 { no match }

在上述pseudo code中,有:

  1. failureFunction 可以用数组表示,在时间复杂度O(m)内计算;
  2. 每次while-loop的迭代中,
    • i increases by 1
    • 或者在 i-j 范围内滑动,这里 i-j increases by at least one,(observe that F(j - 1) < j)
  3. 因此,在while-loop中,迭代的次数不会超过2n;
  4. 综上,KMP算法理想状态下,或者说大部分情况下的时间复杂度是O(m+n)。

示例

图解

在这里插入图片描述

Java代码实现

用BoyerMoore算法的话,
在这里插入图片描述KMP算法的实现
在这里插入图片描述然后
在这里插入图片描述

参考资料

阮一峰的网络日志
知乎–小撸伴读
昆士兰大学COMP7505课件

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值