字符串匹配KMP算法的基本原理及python实现

KMP算法是字符串匹配问题中非常经典的算法。最近查找了很多相关资料,直到看到下面这两篇博客,终于理解了KMP的基本原理。
KMP算法的核心即是计算字符串M每一个位置之前的字符串的前缀和后缀公共部分的最大长度。获得M每一个位置的最大公共长度之后,就可以利用该最大公共长度快速和字符串S比较。当每次比较到两个字符串的字符不同时,我们就可以根据最大公共长度将字符串M向右移动,接着继续比较下一个位置。
强烈推荐大家看一看以下两篇博客,相信能有所收获。
首先推荐看这篇,篇幅较短,没有大量的算法细节,建议先读这篇,对KMP算法的核心思想有所把握:
http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html
在了解基本思想后,建议详细阅读下面这位大神的博客,写的非常清晰,认真研读之后,相信会对KMP有深入的了解,并能编程实现。
https://blog.csdn.net/v_july_v/article/details/7041827
在网上没有查到比较清晰的python解决方案,在这里给出python实现方法,
供参考。(笔者测试了多个测试用例,均通过,如有问题,欢迎指出~)

问题:

搜索字符串S中是否含有模式串P,如果有,返回True,否则返回False

基于python2实现:

def KMP(S,P):
	def next_list_generate(s):
		'''
		产生模式串的next列表,此处为KMP核心部分,强烈建议大家仔细阅读     上面的两篇博客
		'''
		if len(s) == 0 :
			return False
		if len(s) == 1:
			return [-1]
		if len(s) == 2:
			return [-1,0]
		next_list = [0]*len(s)
		next_list[0]= -1
		flag = 2
		k = 0
		while flag < len(s):
			if k == -1 or s[k]==s[flag-1]:
				k    += 1
				next_list[flag] = k
				flag += 1
			else:
				k = next_list[k]
		return next_list
	if len(S)<len(P):
		return False
	next_list = next_list_generate(P)
	match = 0
	flag  = 0
	while flag+len(P)<=len(S) :
		for i in range(len(P)):
			if P[i] == S[flag+i]:
				match += 1
			else:
				flag += match - next_list[i]
				break
		if match == len(P):
			return True
		match = 0
	return False

测试样例:

#instance1
Str = 'freerh'
Pattern = 'erh'
print KMP(Str,Pattern)
#instance2
Str = 'abcd'
Pattern = 'be'
print KMP(Str,Pattern)
#instance3
Str = 'abcdf'
Pattern = 'bcdg'
print KMP(Str,Pattern)

测试输出:

True
False
False

基于python3(python3.8)实现(2020.12.16新增)

def KMP_search(text:str,pattern:str)->bool:
	if len(pattern)>len(text) or len(pattern)==0:
		return False
	def get_next(pattern):
		next_list=[0 for i in range(len(pattern))]
		next_list[0]=-1
		i=-1
		j=0
		while(j<len(pattern)-1):
			if(i==-1 or pattern[i]==pattern[j]):
				i+=1
				j+=1
				next_list[j]=i
			else:
				i=next_list[i]
		return next_list
	next_list=get_next(pattern)
	ti=0
	pi=0
	while ti<len(text):
		if text[ti]==pattern[pi]:
			if pi==len(pattern)-1:
				return True
			else:
				ti+=1
				pi+=1
		elif pi==0:
			ti+=1
		else:
			pi=next_list[pi]
	return False

测试输入:

print(KMP_search('b','b'))
print(KMP_search('bsdfss','bsdfss'))
print(KMP_search('bsdfsa','sa'))
print(KMP_search('b','a'))
print(KMP_search('bsdfsa','ssa'))
print(KMP_search('bsdfsa','bsdfsb'))

测试输出:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值