前言
对于KMP在几年前自己有了解过,时至今日对其有了更进一步的了解。
网络上有各种各样的关于KMP算法的理解,但是很多阅读起来比较困难,我尝试一种能让自己懂的方式来描述一下这个算法
什么是KMP算法
Knuth-Morris-Pratt 算法(简称 KMP)是解决这一问题的常用算法之一,这个算法是由高德纳(Donald Ervin Knuth)和沃恩·普拉特在 1974 年构思,同年詹姆斯·H·莫里斯也独立地设计出该算法,最终三人于 1977 年联合发表。KMP这个算法名字正是取自这三个人的姓氏首字母。
KMP要解决的问题就是给定一个主串(以 S 代替)和模式串(Pattern:以 P 代替),要求找出 P 在 S 中出现的位置,此即串的模式匹配问题。
朴素匹配法(暴力匹配)的时间复杂度 :O(n*m)
KMP的时间复杂度:O(m+n)
整体思路
以下面的字符串为例:
第一轮P串和S串的一个等长度字串进行比较,前5个字符都是匹配的,第6个字符不匹配。
那么这个时候我们就可以有效的利用已经匹配的前缀“ABABA”;
仔细观察已匹配的前缀“ABABA”,S串中的后三个字符“ABA”与P串中的前三位字符“ABA”是相同的。
由此可见,我们只有把这两个相同的片段对齐才有可能出现匹配;
接下来进行第二轮的比较,直接把P串向后移动两位,使得“ABA”对齐,继续从第一轮S串中不匹配字符开始进行比较。
从图中我们可以看出“E”与“B”是不匹配的,那么这个时候的匹配前缀缩短成了“ABA”。
根据第一轮的思路,可以得到新的最长可匹配后缀字串(S串中)和最长可匹配前缀字串(P串中),如下图所示。
接下来进行第三轮的移动,移动P串,让上下两串中的“A”进行对齐,继续从第二轮S串中不匹配字符开始进行比较。
以上就是KMP的整体思路
从上面的分析方法中我们可以了解到,要找到一个字符串前缀的最长可匹配后缀字串和最长可匹配前缀字串成为了这个算法的关键步骤,可以将这些长度存储在一个集合里,