KMP字符串匹配算法

KMP字符串匹配算法

/编辑

KMP完全匹配算法和 Levenshtein相似度匹配算法是模糊查找匹配字符串中最经典的算法,配合近期技术栏目关于算法的探讨,从网上摘取了一些简要的内容,加上自己的一些理解,向大家普及一些这方面的知识,希望能抛砖引玉。

算法简介:

kmp算法是一种改进的字符串匹配算法,由D.E.KnuthV.R.PrattJ.H.Morris同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法)。KMP算法的关键是根据给定的模式串W1,m,定义一个next函数。next函数包含了模式串本身局部匹配的信息。

l KMP算法和传统算法的匹配比较:

1.      传统算法:

         传统匹配思想是,从目标串Target的第一个字符开始扫描,逐一与模式串的对应字符进行匹配,若该组字符匹配,则检测下一组字符,如遇失配,则退回到Target的第二个字符,重复上述步骤,直到整个PatternTarget中找到匹配,或者已经扫描完整个目标串也没能够完成匹配为止。假设模式串Pattern长度为m,目标串Target长度为n,则每次比较最多需要花费O(m)的时间,算法的复杂度为O((n-m+1)*m)。这种算法没有利用匹配过的信息,每次都从头开始比较,速度很慢。

2.      KMP算法:

在传统算法的基础上,当匹配失败后,并不简单地从目标串下一个字符开始新一轮的检测,而是依据在检测之前得到的有用信息,或者说模式串本身的特征信息,取得next函数跳转的位置,直接跳过不必要每次从头检测,从而达到一个较高的检测效率。

l 算法实例说明:

假设在串S=abcabcabdabba中查找T= abcabd

1.      传统算法:

先是比较S[0]和T[0]是否相等,然后比较S[1] 和T[1]是否相等我们发现一直比较到S[5] 和T[5]才不等。如图:

271746424278194.gif

 

当这样一个失配发生时,T下标必须回溯到开始,S下标回溯的长度与T相同,然后S下标增1,然后再次比较。如图:

这次立刻发生了失配,T下标又回溯到开始,S下标增1,然后再次比较。如图:


271746436303493.gif

这次立刻发生了失配,T下标又回溯到开始,S下标增1,然后再次比较。如图:

271746439749921.gif

又一次发生了失配,所以T下标又回溯到开始,S下标增1,然后再次比较。这次T中的所有字符都和S中相应的字符匹配了。函数返回TS中的起始下标3。如图:

271746443965093.gif

2.      KMP算法:

还是相同的例子,在S=abcabcabdabba中查找T=abcabd,如果使用KMP匹配算法,当第一次搜索到S[5]T[5]不等后,如图:

271746424278194.gif

S下标不是回溯到1T下标也不是回溯到开始,而是根据TT[5]==d的模式函数值(next[5]=2),直接比较S[5] T[2]是否相等,因为相等,ST的下标同时增加;因为又相等,ST的下标又同时增加。。。最终在S中找到了T。如图:

271746448803778.gif

此处关键的问题是,为什么KMP算法能聪明的知道应该直接从S[5] T[2]开始比较呢?因为它能够利用已经得到的部分匹配信息来进行过滤。因为我们根据第一次比较得到的结果,如图:

271746424278194.gif

很明显已经匹配了到了部分结果”abcab”,只是由于到T[5]==’d’的时候才无法和S[5]=’c’匹配上的,此时按传统算法T[0]应该重新开始和S[1]比较,但是根据之前的匹配结果S[1]等于T[1],但很明显T[0]不等于T[1],因此比较T[0]S[1](也即T[1])是完全没有必要的。

            以此类推,根据已经得到的结果”abcab”T[0]重新开始比较的时候,应该和S[3](也即T[3])开始比较才是明智的。

因此 next[5]=2这个2表示T[5]==d的前面有2个字符和开始的两个字符相同,且T[5]==d不等于开始的两个字符之后的第三个字符(T[2]=c.如图:

271746453027949.gif

 

也就是说,如果开始的两个字符之后的第三个字符也为d,那么,尽管T[5]==d的前面有2个字符和开始的两个字符相同,T[5]==d的模式函数值也不为2,而是为0

附件为KMP算法的实现java,有兴趣的同事可以试试:

KMPMatchString.java

 





转载于:https://www.cnblogs.com/dimmacro/p/4460838.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值