简介
KMP 算法是 D.E.Knuth、J,H,Morris 和 V.R.Pratt 三位神人共同提出的,称之为 Knuth-Morria-Pratt 算法,简称 KMP 算法。该算法相对于 Brute-Force(暴力)算法有比较大的改进。KMP 算法是一个著名的字符串匹配算法,效率很高,但是确实有点复杂。
KMP算法
我们在匹配两个字符串时,最简单的方法就是暴力匹配,从头开始对比两个字符串,一个一个字符对比,如果遇到不匹配的情况下,把短的字符串向后移一位,然后继续从头比较。这种方法虽然很简单,但是当字符串的长度逐渐增大的时候,因为这个算法的时间复杂度时O(N^2),所以时间会成倍的增加。所以有人就在这个基础上想出了优化方式,就是当你前面的字符串匹配成功时,后续可不可以不从头开始,而是从某一个位置开始去匹配。
前缀表
在知道了想法后就要开始想怎么计算那个位置,这就有了一个概念叫前缀表,英文叫Prefix Table。前缀表中储存的就是我们匹配失败后要挪到的位置。前缀就是从前面看不包括自己的连续子串。
前缀表中储存的是每个前缀字符串的最长前缀和后缀匹配长度,这个描述有点抽象,我们拿图来说。
这样前缀表就生成好了。
计算前缀表
下面就开始计算前缀表了,我们以下面这个例子来说,计算一个字符串最长前缀后缀匹配长度,其实可以看成是一个动态规划问题,因为前缀都是连续,所以我们可以看成是每次在上一个字符串的后面加了一个字符,我们用一个len来记录上一个字符串的最长前后缀匹配长度,每次让新加入的字符和len位置的字符匹配,如果匹配成功,len就加1,然后让Prefix[i] = len。
再来看下面这这个例子,i位置和len位置匹配失败的情况。当匹配失败,我们让len = Prefix[len-1],因为len记录的是上一个字符串的最长前后缀匹配长度,也就是说这个匹配失败,我们会从上一个len来比较,不用从头开始,这样节省了大量的时间。
代码如下,为了后面方便计算,我们让前缀表向后移动一位,把第一位置为-1.
public stati