KMP算法

1. 先讲一下搜索过程

假设我们已经生成了 next 数组,

python 复制代码
def kmp_search(string, patt):
	next = build_next(patt) # 假设我们已经算出了next数组
	i = 0  # 主串中的指针
	j = 0  # 子串中的指针
	while i < len(string):
		if string[i] == patt[j]:  # 字符匹配,指针后移
			i += 1
			j += 1
		elif j > 0:  # 字符失配,根据next跳过字串前面的一些字符, next[j-1]是几字串的指针就跳过几个
			j = next[j-1]
		else:  # 子串第一个字符就失配
			i += 1
		
		if j == len(patt):  # 匹配成功
			return i - j



2. next数组的生成

next 数值代表了在匹配失败的时候子串中可以跳过的字符个数,如果是2就代表我们可以跳过前两个字符的比较,但凭什么可以这么做呢?

如图因为我们之前匹配的最后那两个 AB 和这里跳过的最前面的这两个 AB 是一样的,即两个黄线上的 AB 是一样的。

换句话说对于字串的前四个字符,他们拥有相同的前缀和后缀,长度为2

python 复制代码
"A"的前缀为空,后缀也为空,所以相同前后缀的最长长度为0

"AB"的前缀:A
"AB"的后缀:B
相同前后缀的最长长度为0

"ABA"的前缀:A, AB
"ABA"的后缀:A, BA

"ABAB"的前缀:A, AB, ABA
"ABAB"的后缀:B, AB, BAB
相同前后缀的最长长度为2

"ABABC"的前缀:A, AB, ABA, ABAB
"ABABC"的后缀:C, BC, ABC, BABC
相同前后缀的最长长度为0

(前后缀不包含字符串本身)

next 数组的本质就是寻找子串中相同前后缀的长度

递推求解 next 数组:

这个方法的巧妙之处在于会不断利用已经掌握的信息来避免重复的运算。如下图,假设我们已经知道当前的最长共同前后缀为2

接下来分两种情况讨论:

  • 如果下一个字符相同的话就可以直接构成一个更长的前后缀,它的长度等于之前的加上1
  • 如果下一个字符不同我们就要看看其中存不存在更短的

比如这里的A,它有可能跟下一个字符构成共同前后缀

这一步也不用暴力求解,因为根据我们掌握的信息,字串前后这两部分是完全相同的,也就是说右边这部分的后缀等于左边这部分的后缀:

所以我们直接在左边寻找共同的前后缀即可,而左边的前后缀我们之前已经计算过了,为1,于是我们又回到了最开始的步骤,从A开始检查下一个字符是否相同,如果相同,则可以构成一个更长的前后缀,长度+1即可:

代码:

python 复制代码
def build_next(patt):
	"""
	计算next数组
	"""

	next = [0]  # next 数组(初值元素一个0)
	prefix_len = 0  # 当前共同前后缀长度
	i = 1
	while i < len(patt):
		# 如果下一个字符相同,代表可以构成一个更长的前后缀,则长度+1
		if patt[prefix_len] == patt[i]:
			prefix_len += 1
			next.append(prefix_len)
			i += 1
		# 如果下一个字符不同
		else:
		    # 如果依然不存在,则将next设为0
			if prefix_len == 0:
				next.append(0)
				i += 1
			# 直接查表看看其中存不存在更短的前后缀
			else:
				prefix_len = next[prefix_len - 1]
	return next
相关推荐
逻辑驱动的ken2 分钟前
Java高频面试考点场景题09
java·开发语言·数据库·算法·oracle·哈希算法·散列表
帅小伙―苏16 分钟前
力扣42接雨水
前端·算法·leetcode
AI科技星32 分钟前
精细结构常数α的几何本源:从第一性原理的求导证明、量纲分析与全域验证
算法·机器学习·数学建模·数据挖掘·量子计算
6Hzlia38 分钟前
【Hot 100 刷题计划】 LeetCode 287. 寻找重复数 | C++ 数组判环 (快慢指针终极解法)
c++·算法·leetcode
MegaDataFlowers38 分钟前
26.删除有序数组中的重复项
算法
故事和你912 小时前
洛谷-数据结构1-4-图的基本应用2
开发语言·数据结构·算法·深度优先·动态规划·图论
吴可可1232 小时前
C#合并首尾相连多段线实战
算法·c#
KMDxiaozuanfeng3 小时前
卡梅德生物技术快报|SPR 技术应用|基于 SPR 亲和力的中药活性成分筛选系统实现与数据分析
科技·算法·面试·考试
꧁细听勿语情꧂3 小时前
数据结构概念和算法、时间复杂度、空间复杂度引入
c语言·开发语言·数据结构·算法
Felven4 小时前
B. The 67th 6-7 Integer Problem
数据结构·算法