KMP算法是一种优化的字符串搜索算法。对于给定的长度为n的字符串text,需要从中搜索长度为m的字符串pattern。如果用Brute Force遍历字符串,以每个字符为开始匹配pattern的话,最差时间复杂度为O(m*(n - m + 1))。作为优化,KMP算法的最差时间复杂为O(n)。
KMP算法详细解释可看KMP Algorithm for Pattern Searching。用到的核心概念有三个:前缀(prefix),后缀(suffix),与部分匹配表(partial match table)。例如,字符串"ABC",前缀包括{“A”, “AB”, “ABC”},后缀包括{“C”, “BC”, “ABC”}。部分匹配表是一个与pattern相同大小的数组(即代码中的lps[]),用于存储最大前缀后缀公共元素的长度,但这的前缀与后缀不包括整个字符串本身。例如,lps[i]代表的是pattern中[0, i]的子字符串中前缀与后缀交集中的最长元素的大小。
For the pattern “AAAA”,
lps[] = [0, 1, 2, 3]
For the pattern “ABCDE”,
lps[] = [0, 0, 0, 0, 0]
For the pattern “AAACAAAAAC”,
lps[] = [0, 1, 2, 0, 1, 2, 3, 3, 3, 4]
KMP的算法核心就是通过partial match table来记录pattern的最大前缀后缀公共元素长度,当pattern的某个字符与text不匹配时,利用已经部分匹配的信息,移动pattern的指针,保证text的指针不回溯。图示过程讲解可参考link。
Leetcode-28-Implement strStr(): 给定字符串haystack与needle,返回needle在haystack中出现的位置。
// C++ solution
class Solution {
public:
// method 1: brute force
int strStr1(string haystack, string needle) {
int m = haystack.size(), n = needle.size();
for (