用人话讲一讲KMP是怎么回事

KMP(看毛片)算法,是从一堆字符串里查找相应字符串,该算法的核心是对要查找的字符串进行拆分,算出相应的结果数据,然后进行数据匹配的过程。

这个算法的精髓就是首先查出他的最大重复字符窜(重复部分的字符窜必须是从开头部分算起,比如abcbc,他的最大重复项为0,而abcac,最大距离间隔就是3)的距离间隔m,然后在查找的时候,查看该字符窜与目标字符窜命中部分的长度,如果命中部分的长度>m,则如果没有命中,就移动m个位,如果命中部分<m,那么就移动命中部分长度的间隔,但是这里移动有一个下线条件那就是1

首先举个例子:

从BBC ABCDAB ABCDABCDABDE字符串里查找ABCDABD。

第一步,拆分ABCDABD,看看它里面重复元素的距离间隔是多少,很明显,他的重复元素距离间隔是【AB】CD【AB】D,第一个AB到下一个重复的AB间隔为4

那么现在KMP算法执行的流程是

第一次匹配时,我们发现能匹配上的数据为0因此移动1次,因此从0开始

第二步:重复第一步,我们发现,仍然匹配不了,因此在移动一次,从0开始

第三步:重复第一步,我们发现,仍然匹配不了,因此在移动一次,从0开始

第四次匹配时,我们发现匹配命中为6位,匹配命中的部分,重复值的间隔为4,因此,我们可以直接移动4次,但是从2的位置,即C的位置开始比较

第五次匹配时,我们发现命中的部分为2,但是重复值间隔为0,因此接下来要移动2步。从

第六次匹配时,我们发现名部分为6,然后重复值间隔为4,因此,接下来我们需要移动4步

第七次匹配时,全部命中。

以上原理就是这么简单,但是如何用代码实现呢,这里就来了。

但是这里面有一个问题,那就是解决重合部分的回溯问题,这个问题是啥意思呢,用上面的例子,第四步和第五步讲解

第四步移动4得到第五步,但是在第五步,我们发现了一个问题,那就是第五部的开头要搜索的字符窜AB,其实再第四步就比对过了,这时候按照道理,开始从开头的AB后面的C比较就可以了。

如何让它从C开始呢?

假设我们不考虑被寻找的字符窜是什么,我们只关心要查找的字符窜,以ABCDABD为例,所有可能移动的步数和结果如下:

从这个表里我们可以发现,如果在ABCDABD字符串里,头五个字母编号,我们会发现,如果哪个不符合,就将A标点移动到不符合的位置,但到了第二个B那里,情况变了,不是将A移动到第二个B处,而是第二个A处,而从上面可以总结一个规律,那就是如果用数组表示这7个字符,则会生成如下NEXT数组表:

NEXT数组生成

从这里我们发现这个一个规律,就是字母代表的下标那一行的数字,等于是前面重复数据的个数,而按照这个规律推出来的就是所谓的NEXT数组的表示。

而下面的nextval只不过是三次重复数据出现后的下标表示法,是从next里推出来的

 

 

 

 

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