KMP算法思想——易理解

理解

首先找到字符串不匹配的地方

声明:两个字符串我们定义下面的是模式字符串,上面的是主串。

 也就是箭头左边部分上下字符串是完全匹配的 

2.模式串左右两端有两个子串AB称为模式串的公共前后缀

 3.直接往前移动模式字符串,使得其公共前后缀里面的前缀直接移动到了原先后缀所在的位置

 (由于公共前后缀是匹配的,这样移动,可以保证当前比较指针所在的位置它左边的串上下是匹配的)有人可能会问,这样一下把模式字符串往前移动了几个位置来到公共后缀的位置,中间有没有可能跳过某些匹配的情况,但是其实中间是没有匹配的情况的,可以一步一步来看看

向后移动一个单位

在箭头前会有不匹配的情况 

再向后移动一个单位

 在箭头前面还是会有不匹配的情况

再往后移动一个单位

 这时候,箭头前面的字符串完全匹配,也就是直到公共后缀的位置,箭头前面模式串和主串才匹配。

 一般情况

X所在的位置的字符与子串不匹配,这时候只需要找出X之前那一段字符串的公共前后缀,然后往前移动字符串,使得前缀来到原来后缀的位置,就可以继续往下比较

重复以上动作

1.接下来箭头继续往后面扫描直到找到模式串和主串不匹配的地方

2. 寻找箭头前公共前后缀,。注意:如果字符串当中有多对公共前后缀,我们要取最长的那一对.此时为A,而且确实是最长的没有其他的公共前后缀了.

 3.所以下一步移动模式串,使得前缀与后缀的位置重合

但是这时候发现模式串的长度已经超过了主串,也就是模式串无法和主串匹配,扫描结束。 

显然这种比较次数比幼稚模式串匹配算法要少得多,也就是效率高的多

其实分析这个问题不需要看主串,因为主串箭头前面那一部分和模式字符串箭头前面那一部分的字符是一样的(本来箭头指向的就是两个字符串不匹配的地方)

再举一个例子

1,左端对齐,挨个扫描

 

2.下面来到这个位置发生不匹配

 

找一下公共前后缀,要找最长的那一对,但是不能多于子串的长度,没有意义

 首先找到的是A

接下来继续移动,但是下面这种情况不是公共前后缀

 继续移动,观察

 找到一个公共前后缀

还可以继续移动

 此时不是公共前后缀,继续移动

不要犯迷糊,公共前后缀不可以是自身,所以,综上所述,最长公共前后缀应该是ABA,接下来移动模式串直到后缀的位置

 移动指针发现接下来的都是匹配的了,所以匹配成功。

这就是KMP算法的原理

Next数组的引入

回到刚才不匹配的状态,我们找到了公共前后缀,接下来往前移动,把前缀移动到后缀的位置,这个过程中根本不需要移动主串,那么我们把主串扔掉,一样可以移动到正确的位置。

 所以,对于KMP算法,我们只需要研究模式字符串就够了,把模式串的相关信息挖掘出来之后,就可以和任何的主串进行匹配了。

接下来就以这个字符串为例来研究一下,为了方便处理,我们把它放在一个数组当中,同时标记了数组下标,此时注意我们的模式字符串是从下标1开始,0位置我们什么都没有存,当然那你也可以从0开始存放,都是一样的。

对于计算机而言,在计算机中的表达

假设这个字符串是有可能和任何一个字符串进行KMP算法,那么它的每一个位置上就都可能发生不匹配,假如第一个位置发生了不匹配,按照以上分析的思想,模式串是要往后移动一位的。但是由于串在内存中不会像在动画当中一样去移动,所以表述的时候不用“移动”这个词,而是说成1号位与主串下一位进行比较。

如果2号位置发生了不匹配,我们要寻找公共前缀,发现子串前的长度只有1,而公共子串的长度要求小于小于这个子串的长度,那么公共前后缀的长度就只能是0了,那么模式串就移动到这个位置,这个过程要描述成不含有“移动”这个词的表述方式,就是拿模式串中的一号位置与主串当中的当前位置进行比较,这就是模式串第二号位发生不匹配的时候的处理方法。如果3号位发生与主串的不匹配问题,那么寻找最长公共前后缀,结果找到最长公共前后缀是0,那么处理方法和2号位置是相同的,也就是1号位置与主串当前位置进行比较;对于4号位置,首先要寻找最长公共前后缀,发现长度是1,也就是要移动到后缀的位置才可以继续比较了

 此时,指针指向了模式串的2号位置,根据之前的分析,就是该从这里进行比较,接下来要描述的时候不含有“移动”这个词,也就是二号位与当前位置进行比较

 结束之后看5号位置,

 

寻找最长公共前后缀,发现是AB

 之后移动模式串,就是模式串的3号位置与当前位置进行比较,

 

跟号位置表述相同,就是3号位置与当前位置进行比较;

结束之后看6号位置,首先寻找最长公共前后缀,找到了ABA

 结束之后移动模式串,确定比较的位置,也就是4号位置,与主串当前位置进行比较,

 表述的话就是4号位置与当前位置进行比较;

 

规律:

如果当前公共前后缀的长度为3,得到的结果就是4号位置与主串当前位置开始比较,也就是,如果公共前后缀长度为n,就得到n+1号位置与主串当前位置进行比较,没错,每次开始比较的位置编号其值就等于当前最大公共前后缀长度+1

接下来就继续看7号位置,最长公共前后缀长度为1,那么7号位置的表述就是2号位与主串当前位置进行比较,以此类推,最后得到

 因此得出Next数组作用:当模式匹配串T失配的时候,NEXT数组对应的元素指导用应该用T串的哪个元素进行下一轮的匹配

也就是

 


文章中的图片来源于天勤考研,希望以上内容对你有所帮助,至于代码实现部分,可以参考小甲鱼的视频,文章中有所不足的部分都可以指正,我们共同学习。 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值