KMP算法原理
Next数组
Next数组在KMP算法中也叫做最长前缀后缀表,通过特定方法生成。
对于需要KMP匹配的模式串,构造next数组需要以下方法:
例如字符串 abcabdcaba
对于人工分析,我们进行如下拆分前缀和后缀
人工分析
我们发现对于一个模式串前缀和后缀存在相同字符串的中 相同字符串中的字符对个数 就为该段字符串对应的最长公共前后缀的长度,一个一个拆分字符是模拟计算机中一个一个遍历。
计算机角度分析
上一部分是对于人眼最直观的认识,那么计算机中怎么去求出这个Next数组呢?
我们首先来模拟程序中遍历字符串的过程
可以看见,指针在往右移动的过程中,指针走过的区域是不是就和上面所说的区域对应起来了?
- a
- ab
- abc
- ······
但这只是指针所走过的区域,说到底指针指向的只有一个字符,前面的字符过了就过了,怎么样才能从指针的遍历过程中来确定每一段前后缀的最长公共前后缀呢?
首先,对于模式串的第一个前缀位置,也就是当指针指向第一个字符的时候,该位置只有一个字符``,所以肯定为0。
对于第二个前缀ab
,根据目前的情况我们可以用当前指针加上偏移量来进行对比,如果不相同则该前缀对应的最长公共前后缀也为0。
但是对于第三种情况就出现问题了abc
我们需要对比a
和 c
,以及ab
和 bc
,这样用偏移就会很麻烦,哪怕用双指针也很麻烦。
那么我们根据已知信息能不能方便后面的计算呢?
进一步分析:
在abc
前缀的前面,我们已经计算了ab
的最长公共前缀为0,这意味着前面两个字符不同,那么对于三个字符的前缀,最长公共前后缀已不可能为2。那么我们需要参考最长公共前后缀为1的情况进行对比。也就是从最短的前缀和后缀进行对比,对比a
和c
发现对不上,则该位置也为0。
那么我们来看看下面几种情况
-
abca
已知前面abc
前缀的最长公共前后缀依然是0,那么退而求其次,对比最短前缀然后递增 -
为了每次我们对比前缀和后缀,那么需要两个指针x , y
- 对比
a
和a
发现相等,之前已知abc
中没有相等的前后缀, x
- 对比