之前学习一些数据结构教材上的kmp算法觉得讲的很复杂,要看很久才能明白,最近看了这篇文章觉得对理解kmp算法很有帮助:http://www.geeksforgeeks.org/searching-for-patterns-set-2-kmp-algorithm/ 下面把自己的理解记录一下
kmp算法是用来解决子串匹配问题的,也就是输入是一个原字符串txt
和一个模式串pat
,输出的是所有txt中子串匹配pat的所有位置。我们知道用暴力的算法进行子串匹配复杂度是O(m*(n-m+1)),n是原字符串的长度,m是模式串的长度,而且保证n>m。但是kmp算法复杂度是O(n)。kmp算法需要借助一个辅助数组lps[],大小是m,代表的意义是pat串中最长前缀和后缀相同的长度,lps数组跟txt串没有任何关系,看下面的例子理解一下lps数组的含义:
比如lps[4]=2,原因是最大相同的前缀和后缀就是AA
。那么如何构造lps数组?这里有点类似动态规划的递推的思路,要有一个变量preLen记录上一次的最大前缀和后缀的长度,现在要求lps[i],
- 如果
pat[i] == pat[preLen]
,那么自然lps[i] = preLen + 1
,同时preLen++ - 如果不等,那么更新
preLen = lps[preLen - 1]
(这里用到这个小技巧,不断利用之前的结果往前推,一旦preLen为0,那么lps[i]只能是0)
|
|
构造完lps数组之后,开始从txt中寻找子串等于pat,先看一个匹配例子理解一下如何用lps数组:
贴一下匹配部分代码,里面有注释进行解释
|
|
算法复杂度 O(n)