KMP算法----模式匹配的一种改进算法

  模式匹配的一种改进算法----KMP算法

   这种改进算法是D.E.Knuth与V.R.Pratt和J.H.Morris同时发现的,因此人们称它为克努特-莫里斯-普拉特算法(简称为KMP算法)。该算法可以在O(n+m)的时间数量级上完成串的模式匹配操作。

 

   其改进在于:每当一趟匹配过程中出现字符比较不等时,不需回溯i指针,而是利用已经得到的‘部分匹配’的结果将模式向右‘滑动’尽可能远的一段距离后,继续进行比较。一般情况下,假设主串为s0s1…sn-1,模式串为p0p1…pm-1,从上例的分析可知,为了实现改进算法,需要解决下述问题:当匹配过程中产生“失配”(即si≠pj)时,模式串“向右滑动”可行的距离有多远,换句话说,当主串中字符Si与模式中字符Pj “失配”(即比较不等)时,主串中字符Si(i指针不回溯)应与模式中哪个字符再比较?


   假设此时主串中字符Si应与模式中字符Pk(k<j)继续比较,则模式中字符Pk前面k个字符的子串必须满足下列关系式(f-1),且不存在k'>k满足下列关系式
p0p1…pk-1= si-ksi-k+1…si-1   (f-1)
当主串中字符Si与模式中字符Pj “失配”时,已经得到的“部分”匹配结果是:
pj-kpj-k+1…pj-1= si-ksi-k+1…si-1 (f-2)
由(f-1)和(f-2)推得下列等式
p0p1…pk-1 = pj-kpj-k+1…pj-1    (f-3)
我们称"p0p1…pk-1"为"p0p1p2…pj-2pj-1"的前缀子串,"pj-kpj-k+1…pj-1"为"p0p1p2…pj-2pj-1"的后缀子串。


若模式串中存在真子串"p0p1…pk-1= pj-kpj-k+1…pj-1",且满足0<k<j,则当匹配过程中,主串中字符Si与模式中字符Pj比较不等时,仅需将模式向右滑动至模式中第k个字符和主串中字符Si对齐,此时,模式中头k个字符的子串"p0p1…pk-1"必定与主串中字符Si之前长度为k的子串"si-ksi-k+1…si-1"相等。由此,匹配仅需从模式中Pk与主串中字符Si比较起继续进行。 若令next[j]=k,则next[j]表明当模式中第j个字符与主串中相应字符“失配”时,在模式中需重新和主串中该字符进行比较的字符的位置。由此可引出模式串的next函数的定义: 1.next[j]=-1 当j=0时 2.next[j]=Max{k|0<k<j且"p0p1…pk-1= pj-kpj-k+1…pj-1"}                 

     

      此集合不为空时 3.next[j]=1 其他情况 其中p0p1…pk-1为p0p1p2…pj-2pj-1的前缀子串,pj-kpj-k+1…pj-1为p0p1p2…pj-2pj-1的后缀子串。 KMP算法源代码如下:

 

 

  c语言实现:

 

 

 

 

c++语言实现:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值