意图理解——KMP算法

想写一个算法思路(意图)的系列,从KMP算法开始吧,不讲代码,只讲”为什么要这么想,这么写“,看网上这么讲的还没见到,自己想写的还是必须自己写啊~

KMP一直看书不明白的,看视频真的有帮助,老师会自然而然地说出思路而非书上那般生硬。
B站,严蔚敏奶奶视频教程


一、kmp的目标:

1,防止i指针回溯。

需要重新匹配时,其实前面的已经匹配成功,问题可以转化为模式串的自比较,从而省去i指针的回溯。

2,让j指针回溯得尽量少。

模式串的前缀、后缀最长重复位数可以代表需要跳过几位。


二、一个实例

一位一位比较时
遇到主串i指针的字符 与 模式串j指针的字符 不匹配时。

-------i
abaabcabbbbb
abaabcac
-------j

发生了i指针回溯,同时产生了已经成功匹配序列的错位

-i
abaabcabbbbb
-abaabcac
-j

再一位一位比较……

--i
abaabcabbbbb
--abaabcac
--j
---i
abaabcabbbbb
--abaabcac
---j

突破点是已经成功匹配的字符串,错位后,除了一些特殊情况,必然不能匹配!

那个“特殊情况”就是前缀与后缀的重复,同时,匹配成功的主串、模式串的部分是相等的! 这样next数组仅仅交给模式串就等于主串、模式串都遵守了!
——回到第一步那里,接着可以直接进行下一步:j回溯到模式串的b(从第一步的c)。

-------i
abaabcabbbbb
------abaabcac
-------j

三、原理要点

0,明白什么不用比较,什么还需比较
1,基于已经成功匹配的字符串(已知匹配成功的位数)
2,i回溯会导致已经匹配成功的串错位(主串与模式串),如何防止i指针回溯导致的浪费?——除了一些特殊情况,错位必然不能匹配!
3,特殊情况——只用考虑【已经匹配成功的部分主串(也就是部分模式串!匹配成功的部分代表它们完全一致!)】的错位是否会有”重复“
4,错位时,模式串前缀后缀的重复可以避免重新匹配(模式串与模式串——next数组)
5,next数组标记的有关于当前字符子串前缀、后缀最长重复长度,也就是可以不直接退回j串第一个字符的可以少回溯的重复部分。


四、理解next

教材定义图引自:https://blog.csdn.net/qq_37969433/article/details/82947411
在这里插入图片描述
*注:教材上的”1“是[其他情况],不是[”不匹配时“]
这图上的精确的数学语言看着就让人头疼,不如按着公式试试几个例子。

这是严蔚敏教材P81的next数组值

abaabcac
01122312

验证公式:我们取第4位的”a“,则这个a的next[4]的值是”k=2“,[1到2-1]=[4-2+1到4-1]即【1到1】=【3到3】即 [a]=[a]。
这也应当是”最长前后缀重复长度“

abaabcac
---2----

验证公式:我们取第6位的”c“,则这个a的next[6]的值是”k=3“,[1到3-1]=[6-3+1到6-1]即【1到2】=【4到5】即[ab]=[ab]。
这也应当是”最长前后缀重复长度“

abaabcac
-----3--

下面是回溯j指针的实例。
【现在是f比a】同时,在匹配错误时跳过多少?

---i
abafbcabbbbb
abaabcac
---2----------------next

回溯至2【现在是f比b了】(j=next[j],就是j赋值当前位置的next数组的值,也就是下一步的位置(已经算好了跳到哪里))

---i
abafbcabbbbb
--abaabcac
---1-----------------next

回溯至1(回溯到头都没有,之前的整串又配不上,GG,真匹配不上了)
这里发现了又匹配到了f对a,这个涉及”对KMP算法的一种改进“,书上有。

---i
abafbcabbbbb
---abaabcac
---0------------------next

关于前缀后缀放张图,下图引自:https://www.cnblogs.com/zhangtianq/p/5839909.html
在这里插入图片描述

注意,next[j]内的值不代表j之前的子串前后缀的最大长度,而是“当模式串中第j个字符与主串相应字符‘失配’时,在模式串中需要重新和主串中该字符进行比较的字符的位置”。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章