2021-07-22 粗略学习一下KMP -- LeetCode 28
KMP: 参考 https://www.zhihu.com/question/21923021
核心思想:跳过不可能成功的字符串比较,利用了Next数组
1. 构建next数组
精髓:快速求Next数组(最长公共前后缀数组)
next数组的完整定义:
定义 “k-前缀” 为一个字符串的前 k 个字符;“k-后缀” 为一个字符串的后 k 个字符。 k 必须小于字符串长度。
next[x] 定义为: P[0]~P[x] 这一段字符串,使得k-前缀恰等于k-后缀的最大的k.
快速构建next数组,是KMP算法的精髓所在,核心思想是“P自己与自己做匹配”。
采用递推的方式求出next数组。如果next[0], next[1], ... next[x-1]均已知,那么如何求出 next[x] 呢?
如果P[x] = P[next[x-1]] 则 next[x] = next[x-1] + 1;
如果P[x] != next[x-1] 则
abcbaabcba|b
01234|56789|10
A前缀|B后缀 | x
next[9] = 5 (abcba) 但是 P[10] != next[9]
观察一下,P[x]的k-前缀,一定满足A-前缀的前缀 = B-后缀的后缀+x, 而A = B,所以就是求A自己的最长公共前后缀,
即next[next[x-1]] ==> next[5] ==> 1, 此时P[10] = b = P[1], 所以next[10] = 1 (如果还不相等,就继续缩短,求next[1]...)
2.根据next数组移动标尺进行匹配
LeetCode 28:
/**
* 28-Implement strStr()-KMP-Easy
*
* 时间复杂度:O(n+m),其中 n 是字符串 haystack 的长度,m 是字符串needle 的长度。我们至多需要遍历两字符串一次。
*
* 空间复杂度:O(m),其中 m 是字符串 needle 的长度。我们只需要保存字符串 needle 的前缀函数。
*
*/

浙公网安备 33010602011771号