KMP算法其实就是字符串匹配的一种高效算法,通常称作模式匹配;
本文结构如下:
一、朴素的匹配算法
1、匹配的概念
2、朴素算法原理
3、代码实现
二、KMP算法
1、KMP算法简介
2、KMP算法原理详解
3、求出next()函数
4、代码示例
一、朴素的匹配算法
1、匹配的概念
如下图所示,就是模式串T与主串S匹配成功,模式串首尾间的各个元素与主串之间的某一段元素完全相同
2、朴素算法原理
将模式串中的元素与主串中的元素逐个匹配,如果失配,则模式串向右滑动一个元素,与主串继续进行匹配,如下图所示
3、代码实现
#定义朴素匹配的函数
#主串参数 s ,模式串参数 t
def simple_matching(s, t):
s = list(s)
t = list(t)
m, n = len(s), len(t)
i, j = 0, 0
while i < m and j < n:
if s[i] == t[j]:
i += 1
j += 1
else:
i = i - j + 1
j = 0
if j == n:
return i - j
return 0
s = 'ababcabcacbab'
t = 'abcac'
print(simple_matching(s, t))
>>>5
二、KMP算法
1、KMP算法的简介
百度百科的解释:KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法)。KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个next()函数实现,函数本身包含了模式串的局部匹配信息。
关于上段解释,看了也基本等于没看,不明白在说什么,但其核心意思是以下几点:
1、利用匹配失败后的信息,进行下次匹配
2、通过next()函数实现
通俗的描述一下KMP算法。
首先,朴素算法是这样说的:
将模式串中的元素与主串中的元素逐个匹配,如果失配,则模式串向右滑动一个元素,与主串继续从 j = 0 进行匹配
KMP算法描述相近:
将模式串中的元素与主串中的元素逐个匹配,如果失配发生在主串 元素S[ i ]与模式串元素 T[ j ] 上,那么模式串 t 向右滑动尽可能多的元素个数后,模式串 T[k] 与主串 S[ i ] 继续匹配。
KMP算法的核心与重点就是通过next()函数求出 k 值,这样就不用向朴素算法那样每次只滑动一个元素,然后又从 j = 0开始匹配。
2、KMP算法原理详解
上面对于KMP算法的文字解说,不直观,也不容易理解,下面用图对KMP原理进行说明;
由上可知此时求出k值就是该算法的核心问题,k值就是通过next()函数求解出来的,不同的 j 对应对应不同的k值;
即可以得出next[j]函数的定义:
对于next[j]的各种取值方式,说明如下:
此时举例的处next[j]的值
3、求出next()函数
由以上可知next()函数的求解是KMP算法的核心内容。
下面讲解如何求出next(j)函数
关于next[j]函数值,就有上面的方法求得
4、代码示例
#定义next_kmp()函数,求出next[j]的值
t = "abaabcac"
def next_kmp(t):
t = list(t)
j, k ,n = 0, -1, len(t)
pnext = [-1] * n
while j < n-1:
# k == -1的意义就是说此时的k值不存在
# 当k不存在时,此时的pnext[j] = 0
if k == -1 or t[j] == t[k]:
j, k = j+1, k+1
pnext[j] = k
else:
k = pnext[k]
return pnext
print(next_kmp(t))
"""[-1, 0, 0, 1, 1, 2, 0, 1]"""
s ='ababcabcacbab'
t ='abcac'
#pnext列表作为求得的next(j)函数
#s为主串,t为模式串
def matching_kmp(s,t,pnext):
s = list(s)
t = list(t)
i, j = 0, 0
m, n = len(s), len(t)
while j < n and i < m:
if j == -1 or s[i] == t[j]:
i, j = i+1, j+1
else:
j = pnext[j]
if j == n:
return i - j
return -1
print(matching_kmp(s,t,pnext = next_kmp(t)))
"""5"""
以上就是KMP算法的代码
总结:
朴素算法的时间复杂度O(n*m),但在实际情况中接近O(n+m),而只有当模式串部分匹配较多的情况下,KMP算法才会更为高效!