Python ---- KMP(博文推荐+代码)

既解决完后宫问题(八皇后问题)后,又利用半天的时间完成了著名的“看毛片”算法——KMP。对于初学者来说这绝对是个大坑,非常难以理解。

在此,向提出KMP算法的三位大佬表示诚挚的敬意。!!!牛X!!!

首先,先介绍一下什么是KMP算法:KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法)。KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是实现一个next()函数,函数本身包含了模式串的局部匹配信息。时间复杂度O(m+n)。[1]    

In a word: !!!敲黑板!!!, 在进行字符串匹配时,有普通群众思维和学霸青年思维

普通群众思维就是暴力破解,即将主串中所有与模式串长度一致的连续子串与模式串比较,这个过程中,主串索引会存在回退的过程,大大拉低效率。

学霸青年思维就是KMP匹配,在匹配时,主串索引一直是向前,不退后,只改变模式串的索引,这样匹配效率就大大提高了。


 

 

在KMP算法里,主要有两大问题需要理解:   KMP原理        next数组计算 ,接下来会在对这两部分尽量进行解释一下。

 

KMP原理

首先我先放一篇我认为的比较好的博文资料,作为小白的我,也是看着博文一点一点慢慢学习的。http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html

这篇博文我觉得对于初学者而言,足以理解KMP的原理了。其核心思想即为:,

在主串与模式串中各存在一个比较指针,指针所指的地方即为程序比较的地方,利用对模式串的信息的充分掌握,使其在与主串匹配的时候,灵活改变比较指针,使主串的比较指针一直向前,绝不退后。

 用盗墓笔记中的一句话概括即为,"小三爷你大胆的往前走啊,往前走,莫回呀头"。

在这其中,最关键的就是在匹配的过程中,如何移动其比较指针的位置? 这就是大名鼎鼎的next数组

 

 

Next数组

看了网上那么多的解释,我觉得这一个版本的解释最好懂,真是豁朗开朗http://www.cnblogs.com/tangzhengyue/p/4315393.html,由于自身水平有限,所以这里就不多说什么了,我怕越说越糊涂。关键就是计算模式串中每个字母

最长前后缀匹配。前后缀的解释在介绍KMP原理的那篇博文里已经写的非常清楚了。

下面就直接上代码吧,这样来的比较直接。

 

代码

def getNext(t):
    j, i = -1, 0
    next = [-1]*len(t)
    while i < len(t)-1:
        if -1 == j or t[i] == t[j]:
            i, j = i + 1, j + 1
            next[i] = j
        else:
            j = next[j]
    return next

def KMP(s,t):
    next = getNext(t)
    j, i = -1, -1
    while j != len(t) and i < len(s):
        if s[i] == t[j] or j == -1:
            i, j = i + 1, j + 1
        else:
            j = next[j]
    return (i-j,True) if j == len(t) else "None"


print(KMP("ababxbabcdabdfdsss","abx"))

 

 

本来试着去解释一下程序,可是发现真的很难解释,next数组的求解程序中最关键的是如何初始化。KMP程序就相对比较好理解了。

好吧,最好的方法就是将代码放在IDE中单步调试,的每执行一部查看变量的情况,这样结合原理理解的最快。

 

 

 

 

[1]. 摘自百度百科KMP词条

posted @ 2017-08-31 15:02  TomHawk  阅读(712)  评论(0编辑  收藏  举报