参考文章及博客!感谢各位大佬的精彩讲解!
2、The Knuth-Morris-Pratt Algorithm in my own words
附加自己的一些理解!图片引用上述博主,想要详细了解的请参考上面文章!
(1)首先理解KMP算法,我个人认为你必须要理解:上面各位大佬都有介绍
- 什么是PMT?这个需要你了解一下?
- 需要了解什么是字符串的前缀和后缀?
- 如何使用PMT?
前缀:字符串中的所有字符,并以一个或多个结尾。“ S”,“ Sn”,“ Sna”和“ Snap”都是“ Snape”的适当前缀。
后缀:字符串中的所有字符,以一个或多个开头开头。“ agrid”,“ grid”,“ rid”,“ id”和“ d”都是“ Hagrid”的适当后缀。
移动位数公式:已匹配的字符数 — 对应的部分匹配值
(2)Next数组:
next数组是一个一维的整型数组
数组的下标代表了:已匹配前缀的下一个位置。
元素的值表示:最长可匹配前缀子串的下一个位置。
在任何一个位置,能匹配的最长长度就是当前位置的next的值。如何理解这句话呢?
比如第一个,当模式串的第一个和主串的第一个不匹配时,就表示没有前缀,更没有最长可匹配前缀子串;因此能匹配的长度就是0,而且当前位置也是0,于是就有:next[0]=0
如果是G、GT、GTGTGC这三种情况,并不存在最长可匹配前缀子串,所以对应的next数组元素值(next[1],next[2],next[6])同样是0
当匹配字符串是GTG时,最长可匹配前缀是G,对应数组中的next[3]=1;
当匹配字符串是GTGTG时,最长可匹配前缀是GTG,长度是3,于是对应数组中的next[5]=3
当匹配字符串是GTGTGC时,不存在最长可匹配前缀,长度为0,于是对应数组中的next[6]=0
有了next数组,我们就可以通过已匹配前缀的下一个位置(坏字符位置),快速寻找到最长可匹配前缀的下一个位置,然后把这两个位置对齐。
移动位数公式:已匹配的字符数 — 对应的部分匹配值
参考上面这句话,可以理解为:主串不动,按照移动位数公式进行移动,上图已匹配字符串长度为5,对应最长匹配前缀为3,则移动步数为:2=5-3。然后按照这个方法依次向后移动即可!