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
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)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