数据结构关于串的KMP算法的理解高手请进
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构关于串的KMP算法的理解高手请进相关的知识,希望对你有一定的参考价值。
求串模式匹配KMP算法的详细解释和理解过程,重谢
KMP 算法是一种字符串的模式匹配算法,参看严蔚敏数据结构一书,里面讲的很清楚。基本的字符串匹配算法是将被匹配的字符串S和模式串T 逐个字符进行比较。例如:S中有10个字符,T中有5个字符。S串初始的匹配位置为3.则从S中的第3个字符与T中的第一个字符匹配,若相同则S的第4个字符与T中的第2个字符匹配。直到匹配成功或者出现失配字符。当出现失配情况下,移动标识S中当前进行比较的字符指针,会退到第4个字符处。然后,重复这一过程。简单说,基本的字符匹配算法是通过移动被匹配的字符串S,进行比较字符的指针位置来完成字符匹配的。
而KMP算法刚好相反,在整个匹配过程中S中当前比较字符的指针并不发生回退现象,当出现S中的字符与T中的字符失配的时候。通过改变T的当前比较字符位置的指针来确定当前S中的字符该与T中哪个字符进行比较。简单说,通过模式字符串T的当前比较字符的指针的回退来完成字符匹配。
当理解了KMP算法通过改变T的当前比较字符位置的指针来完成匹配时,接下来要理清的是模式字符串T中的字符指针在失配的情况下是如何移动的。
以严蔚敏数据结构一书中KMP为例,对于模式字符串T,KMP维护了一个对应于T中每个字符弱发生失配情况下,指针回退到哪一位置的数组。当被匹配串S与模式串T发生失配的情况下,T读取数组中相应记录的位置,讲指针回退。如果回退后仍然失配则S的当前比较字符位置指针+1,T串指针回到第一个字符处。
由此可见获取数组中存储的数据是KMP算法的关键,书中的公式看起来有点抽象。数组中的存储指针的位置是根据,模式串T与自身的匹配过程获取的。
实际上是说,模式串T的第一个字符,如果出现失配则不会回退;当前比较位置的字符向前N-1位的子串恰好与T中从第一个字符起止N-1个字符形成的子串相等,且N小于当前位置,满足这些条件的N的最大值即为T当前位置指针回退的位置,然后迭代此过程,直到T本身匹配或回退到第一个字符位置仍不匹配,则当前位置的对应的回退位置指针指向T中的第一个字符所在位置。
讲的还不是很清楚,主要是对比一下基本的字符匹配算法和KMP的不同。一个是通过移动被匹配字符串比较字符的指针来实现匹配,一个是移动模式字符串的当前比较字符的位置指针来实现匹配。对于匹配串字符回退位置这个计算书中已经很清楚,根据算法单步调试一次自然就理解了。 参考技术A 主要理解next[j]的含义即可,当然还有next函数的改进算法
关于KMP算法中模式串的移动不会产生漏解的证明
在KMP算法中我们都知道,当主串与模式串发生失配时,主串的指针不用回溯,而模式串根据最大公共前后缀移动到相应的位置,重新进行匹配,如下图:
由于红色的部分是直接被跳过的,因此有个疑问是,这样子移动会不会跳过恰好与模式串匹配的的位置呢?也就是说在红色的这些部分中,是否存在与模式串完全匹配的某个起始位置,如下图:
事实上,这种情况是不会成立的。这是因为我们是根据最大公共前后缀来移动模式串,所以保证了这种情况是不会发生的。
下面我们用反证法来证这个这个结论是成立的。也就是:如果我们根据最大公共前后缀这一法则来移动模式串,那么在跳过的位置中,不会存在以某一个位置为起点,使得主串与模式串完全匹配。
我们先考虑最简单的情况,也就是最大公共前后缀的长度为1的情况:
然后呢,我们假设存在某一个跳过的位置,以这个位置为起点使得使得主串与模式串完全匹配。
然后根据上面的这个匹配结果,我们可以推出下面的结论:
也许你现在还发现不了什么,现在让我们把这个模式串再次移动到它之前发生失配的位置:
你发现了吗,根据推理的结果,现在模式串中最大公共前后缀是“ABCA”,也就是说最大公共前后缀的长度为4,这与我们一开始的条件“最大公共前后缀长度为1”矛盾了。
虽然我们是以最大公共前后缀长度为1进行反证的,但事实上,无论最大公共前后缀的长度为多少,都可以用同样的方法得到相同的结论。比如可以用归纳法。或是对于任意长度的最大公共前后缀,把整个最大公共前后缀等价看作为长度为1,然后用上面的方法同样得证。
所以,我们就可以得出一开始的结论了:如果我们根据最大公共前后缀这一法则来移动模式串,那么在跳过的位置中,不会存在以某一个位置为起点,使得主串与模式串完全匹配。
参考资料
反证法证明:为什么KMP算法不会跳过(漏掉)正确的答案:https://blog.csdn.net/qq_21989927/article/details/109520767
以上是关于数据结构关于串的KMP算法的理解高手请进的主要内容,如果未能解决你的问题,请参考以下文章