KMP算法

1.KMP算法定义

KMP算法是由D.E.Knuth、J.H.Morris和V.R.Pratt发明的一种字符串匹配算法,因此命名为KMP算法。

2.KMP算法求解的问题

KMP算法主要是为了找到子串P在主串T中的位置,即查找主串是否包含子串,如果包含,则返回包含的起始位置。

3.KMP算法原理

在这里插入图片描述
上图可以看到,当已经匹配了部分信息后,发现不能完全匹配,此时保持i指针不回溯,只移动j指针,让子串尽量移动到有效的位置。
所以KMP算法的重点在于j指针下一步移动到哪里?
在这里插入图片描述
上图,可以看到C和D不匹配了,要把j移动到B的位置,即下标为1的位置,因为前面的A可以继续匹配。
在这里插入图片描述
当匹配失败时,j要移动的下一个位置如何计算?
假设j要移动的下一个位置为k,则下标为[0~k-1]和下标为[j-k,j-1]之间的字符是相同的。
在这里插入图片描述

怎么求k呢?因为在子串P的每一个位置都可能发生不匹配,也就是说我们要计算每一个位置j对应的k,所以用一个数组next来保存,next[j] = k,表示当T[i] != P[j]时,j指针的下一个位置。

4.KMP算法实现

#求解next数组
def cal_next(ptr):
	next = [-1]
    # ptr第一位的没有最长前后缀,直接赋值为-1
	k = -1
    # k代表最长前后缀长度,赋值为-1
	for p in range(1, len(ptr)):
        # 从第二位开始遍历ptr
		while k>-1 and ptr[p]!=ptr[k+1]:
            # 假设已有最长前缀为A,最长后缀为B,B的下一位ptr[p] != A的下一位ptr[k+1]
            # 说明最长前后缀不能持续下去
			k = next[k]
            # 往前回溯,尝试部分前缀,而非从第一位开始重新寻找最长前缀
		if ptr[p] == ptr[k+1]:
            # 如果A B的下一位相同
			k = k + 1
            # 最长前后缀长度 + 1
		next.append(k)
            # 第p位的最长前后缀赋值为k
	print('next: ', next)
	return next

#KMP算法
def kmp(str, ptr):
	next = cal_next(ptr)    # 求解next
	k = -1    # 此处k相当于ptr中已匹配的长度,类似一个指针指向ptr中已匹配的最后一位
	num = 0    # str中ptr的数量
	for p in range(len(str)):
        # 遍历str
		while k>-1 and str[p] != ptr[k+1]:
            # 假设str中的A片段和ptr中的前A位已匹配,但A的下一位和ptr中A+1位不匹配
			k = next[k]
            # 放弃A片段中的前若干位,因为它们不可能再匹配了
            # 用A片段的后若干位去匹配ptr中某一个最大前缀,像上面矩形图所示
		if str[p] == ptr[k+1]:
            # 如果A的下一位和ptr中A+1位相匹配
			k = k+1
		if k == len(ptr)-1:    # 如果ptr走到尽头
			num = num + 1    # 匹配到了一个
			k = next[k]
	return num
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值