KMP算法-易懂版
本文参考b站视频讲解:https://www.bilibili.com/video/BV1jb411V78H?from=search&seid=13583309911591953737 强烈推荐!!!
一:定义
Knuth-Morris-Pratt 字符串查找算法,简称为 KMP算法,常用于快速查找一个母串S中是否包含子串(模式串)P,以及P出现的位置 。由于简单的暴力匹配中,每次遇到不匹配的位置时都要回溯到母串上一次的起点 i +1的位置上再次从子串的开头进行匹配,效率极其低下,故而KMP算法应运而生,减少回溯过程中不必要的匹配部分,加快查找速度。
二:kmp算法求解步骤描述
若当前不匹配的位置发生在母串位置 i,子串位置 j 上,则:
- 寻找子串位置 j 之前元素的最长且相等的前后缀,即最长公共前后缀。记录这个长度。
- 根据这个长度求 next 数组
- 若 j != 0, 则根据next [j] 中的值,将子串向右移动,也就是将公共前缀移到公共后缀的位置上,(代码表示为:j=next [j],注意 i 不变),即对位置 j 进行了更新,后续子串直接从更新后的 j 位置和母串 i 位置进行比较。
- 若 j == 0,则 i+1,子串从j位置开始和母串 i+1 位置开始比较。
综上,KMP的next 数组相当于告诉我们:当子串中的某个字符跟母串中的某个字符匹配失败时,子串下一步应该跳到哪个位置开始和母串当前失配位置进行比较。所以kmp算法可以简单解释为:如子串在j 处的字符跟母串在i 处的字符失配时,下一步就用子串next [j] 处的字符继续跟文本串 i 处的字符匹配,相当于子串一次向右移动 j - next[j] 位,跳过了大量不必要的匹配位置!!!
再来一个,此时最长公共前后缀为ABA!长度为3!

四:kmp算法关键步骤之二,求next[ ] 数组
由步骤一,我们可以得到子串每个位置前面元素的最长共同前后缀,注意子串第一个位置是没有前后缀的,所以长度为0!
例:子串ABCDABD的最长公共前后缀可表示如下。

于是再求next[] 数组,表示下一次比较时 j 在子串的位置,注意子串位置从0 开始!!!另外子串第一个元素的next值设为-1,表示当第一个元素不匹配时,不对 j 进行操作,而是对母串 i 位置加1。而其他位置的元素则为最长公共前后缀长度+1。(但由于这里子串位置是从0开始的,所以next值和长度值相同,但实际next值比长度值多1,注意理解啊!)

最后,总结一下,当子串位置 j 元素发生不匹配时,就查找next数组,找到下一次子串比较的起始位置 j = next [j],从而继续和母串 i 位置比较。而当next = -1时,j 不变,只进行 i +1 操作即可.
(Over, kmp算法代码部分后续奉上!)
浙公网安备 33010602011771号