KMP是一种高效的串查找算法,其主要特点有是不回溯主串,特别适合如边传边找的网络传输场景。
为了做到这一点,KMP算法要提前处理模式串,目标是知道在匹配失败时,如何回退模式串指针。当匹配发生失配时,我们不想像朴素算法那样,把模式串完全移回开头,而是利用已经匹配过的信息,把它“智能”地向右滑动一段距离。
你可以把这个回溯过程想象成模式串的滑动,如果匹配失败,就向右滑动模式串,到模式串的最长前缀和当前主串位置point前的最大后缀对齐,由于在此之前主串当前位置前已经和模式串当前位置前匹配上,所以其实可以直接使用模式串的数据,而不需要回退主串。
Example:
主串 ABABABCA 模式串 ABABX

也可以看看下面这个动画演示:
KMP 匹配演示
准备就绪
S 主串:
P 模式:
nextval:
所以实际我们只要提前计算好在每个位置匹配失败时会回落到什么位置就行了。这个东西就是next数组,保存在匹配失败时模式串跳回什么位置。
计算next数组很简单,就是拿一个point在模式串上扫描,假设在这个位置匹配失败时,模式串会回落到哪里,就是找point前到最长公共前后缀。

我们这里采用以0为开头的标记。
| |
但是我们发现,如果要跳回去的那个目标和现在失败的位置是一样的,那必然还是失败,会导致多次跳跃。那我们为什么不在生成next数组时就帮他跳好呢?
于是便出现了nextval这个优化的版本:
| |
也可以看看下面这个动画演示:
Nextval 生成
Index:
P (模式):
nextval:
