KMP的自我研究之路(一)

经过一天的酝酿思考,我尝试去理解KMP算法的创造过程,最终得出了那么一点皮毛,今天我就来记录一下我的结果吧

首先,介绍KMP算法的详细资料网络上有很多,大家随意google、wiki、百度应该都能找到了。

我这里要讲的不是KMP算法要怎么实现,而是KMP算法的出现过程,这个过程是我自己原创的,不具有任何绝对的说法,重点只是在于帮助自己或者别人理解这个让人难以理解的东西。

【注:有关以下术语的解释看最后面的分割部分】

下面就是我的思考路径:

首先我们随便找两个字符串,一个称为”主串“,另一个称为”匹配串“,我们的任务就是要在”主串“中找到一段与”匹配串“匹配的子字符串的位置,那么最简单的思路应该是下面这样的:


用匹配串主串的0位置开始进行字符比较,一直比较到4位置的时候,发现4位置字符并不相等,这时候用匹配串从主串的1位置进行字符比较,同样发现不相等,继续用匹配串从主串的2位置进行比较······整个过程就是通过每次移动匹配串1个位置来重新与主串重新比较。

以上这样一个比较过程就是最容易想到的,但是这样的比较过程效率不高,我相信很多人都知道这样效率不高,但是我们凭什么说这样的效率不高,除非我们给出一个理由出来是吧。下面我就说说我自己得出的理由:当我们发现主串和匹配串的某个字符不相等的时候,这里有一个条件是成立的,就是主串和匹配串中,主串的“前部分串“和匹配串的”前串“必定匹配,上图中的前部分串就是0~3位置:abab,然而我们发现按照上面这样的比较过程,我们没有利用这个条件,而是忽略它直接进行下一次比较。那么问题来了(当然不是挖掘机到底哪家强?尴尬),主串的”前部分串“和匹配串的”前串“相等究竟有什么用?下面我用匹配过程图来说明:


整个匹配过程是通过移动匹配串来比较的。如图,第1次匹配失败的时候,移动后的匹配串需要满足一个前提条件才能继续同主串的4位置比较字符(这里有人会想,我下一次匹配不是跟主串的4位置比较字符,而是主串的1位置啊。那你跟1位置比较字符的时候,到后面是不是同样需要跟4位置比较字符),这个前提条件就是移动后匹配串的”前串“必须同主串的”前部分串“相等,只有相等了,我们才有必要继续比较4位置。所以,我们看的出第2次匹配这个过程是没有必要的,因为匹配串ababc中b前串为”aba“,而这个”前串肯定不会跟主串4位置的”前部分串"···b”匹配,因为这2个串的最后一个字符都不相等,用下图表示为:


所以,第2次匹配是没必要进行的步骤,现在我们来看看第3次匹配,第3次匹配是匹配串ababc中a的“前串为“ab",而这个前串恰好能够跟主串4位置“前部分串”“···ab”匹配,用下图表示为:


第3次匹配满足了前提条件,所以我们才有必要进行主串4位置的比较。

到此为止,我们思考路径是这样的:

匹配失败时,我们发现该位置继续匹配的前提条件:移动后匹配串的“前串”必须同主串的“前部分串”相等

从而发现中间有一些匹配过程是没有必要的

如果我们能够找到一段匹配“失配位置前部分串前串话,那么我们就可省去中间这些不必要的匹配过程,直接用前串的下1个位置(下面我们称为下一匹配位置与主串失配位置比较。如果相等,那么继续比较;如果不相等,那么同样找到当前匹配串中失配位置下一匹配位置与主串”失配位置“比较······

到这里,问题就转化为:

在匹配串中,找到失配位置下一匹配位置,使得下一匹配位置的“前串匹配失配位置前部分串,且这前串长度最大(下面我们称为最长前串),才能保证向右移动的距离不会过大,避免造成遗漏的情况。

这个问题的求解就跟主串没有任何关系了,只跟匹配串自身有关,因为我们是在匹配串中找“失配位置”的下一匹配位置

只要找出匹配串每个字符的下一匹配位置,那么我们就解决了在匹配主串失配时该如何移动的问题,提高效率。


到这里,我们的目标也就是找出匹配串中每个字符的下一匹配位置

【注:至此,先理解以上内容,再看我的下一篇文章:KMP的自我思考之路(二)】

以上所写均是我个人的理解,有任何建议或者意见,欢迎大家跟我一起讨论偷笑

====================割=========================

以上内容所涉及的我自己创造的”术语“:

主串:被搜索的串

匹配串:搜索的串

失配位置:主串与匹配串匹配过程字符不相等的位置,包括主串失配位置和匹配串失配位置

前部分串:失配位置前面的一部分串,这部分串与失配位置邻接

前串:匹配串中从头部到失配位置(不包括)为止的子串

下一匹配位置:主串与匹配串发生失配时,匹配串中与主串失配位置进行下次比较的位置

==============================================

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值