码迷,mamicode.com
首页 > 其他好文 > 详细

关于字符串精确匹配

时间:2016-09-05 01:41:59      阅读:286      评论:0      收藏:0      [点我收藏+]

标签:

0 引子

嗯,开始之前先介绍几个概念:
目标串:也就是主串,待匹配的串。
模式串:去匹配的串。
子串:原串中的某一连续片段。
前缀:原串前面连续部分组成。
后缀:原串尾部连续部分组成
其实,不用被这些术语搞晕,更不必记忆,转化为自己的东西,理解了就好。

抛个问题先:
现在有两个字符串,其中一个是模式串abcabcacab,另一个是目标串babcbabcabcaabcabcabcacabc,用什么方法能快速判断目标串中是否包含模式串。

学习是个循序渐进的过程,学习算法尤其如此,所以我们由经典算法开始,一步一步深入。
经典的算法思想就是挨个匹配,失配了就整体对齐到下一位继续匹配。
step1:

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
b a b c b a b c a b c a b c a a b c a b c a c a b c
a b c a b c a c a b                                
N                                                  

第一位不匹配。

step2:

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
b a b c b a b c a b c a b c a a b c a b c a c a b c
  a b c a b c a c a b                              
        N                                          

第四位不匹配。

太多就不展开了,这样依次下去,最后肯定可以得出正确的结果。

哎,太容易想到的往往效率不高,经过上面的介绍,大家应该对这个问题有了自己的认识,我一直觉得,想要解决问题一定要对问题本身有深刻的认识,这也是我一直跟队友强调的。如果没有知其然,知其所以然的态度,建议不用继续看下去,毕竟下面要说的单模式匹配KMP算法和BM算法,都出来这么多年了,很多库都有封装,对于很多人来说真的是会用就行。

1 KMP算法

有时刷一些字符串相关的题时,经常会用到KMP算法,其实时间长了,自己也有点忘,就直接依靠以前的模板了,现在网络方便了,自己却变懒惰了,扪心自问:你能给一个完全没这方面基础的人,讲清楚什么是KMP算法吗?

KMP算法是三个人共同提出的,K,M,P分别是这三个人名字的首字母。KMP算法的主要思想是,利用模式串自身的信息,得到next表,next表主要用于失配时的跳跃。

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
b a b c b a b c a b c a b c a a b c a b c a c a b c
          a b c a b c a c a b                      
          Y Y Y Y Y Y Y N                          

上面是匹配过程中的一个状态,为了叙述方便,现在将模式串称P,目标串称为T,现在T[7] != P[12],观察下我们发现1. T[3~6] = P[8~11] 2. T[0~3] = T[3~6],发现这两点应该没什么难度。代换下,进一步发现T[0~3] = P[8~11],这样我们就不用像经典的算法那样,一次只跳一步,现在我们可以直接跳四步,直接去匹配第五位。

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
b a b c b a b c a b c a b c a a b c a b c a c a b c
                a b c a b c a c a b               a
                         ?                          

根据上面的结论,前四位匹配肯定成功,直接从第五位开始比较。

通过上面的分析,我们尝到了KMP思想的甜头,一次跳跃了四位,避免了很多无效的比较。仔细的观察下,上面的做法其实只用到了模式串的特性,和目标串并没什么联系,如果我们提前得到一张模式串的next表,那么失配时,不是可以直接去查表然后计算如何跳跃吗?嗯,对!关键是怎么得到这张表。

得到next表前,我们先要得到这样一张表,前缀自包含的长度,还是举个例子吧,对于上面的模式串T,我们求T[5]的前缀自包含长度,abcabcacab主要就是求T[0~4]中T[0~x] = T[4-x~4]中x的值,显然这里的x=1,那么T[5]前缀自包含的长度就是2,移动的步数 = 已匹配的长度 - 前缀自包含长度 = 5 - 2 = 3。也就是说在T[5]处失配时,直接向前跳3步,因为已经匹配的长度等于5,即T[0~4],前缀自包含长度等于2。

KMP的精髓也就next表,而next表的核心是前缀自包含长度,现在大家应该比较清晰了,梳理下思路就可以自己写出来了。

比较晚了,下面的BM算法,AC算法,WM算法先欠着。 0. 0

2 BM算法

这货的效率平均比KMP高3~4倍(要知道,KMP已经是O(n)的!),平时编辑器里的ctrl+F,grep之类的都是使用的这个算法。但是这个算法的核心和KMP没什么大的区别,只是换了种方式,再加上了一些自己的规则。

3 AC算法

多模式KMP算法。嗯,姑且这样理解吧!

4 WM算法

多模式BM算法。嗯,姑且这样理解吧!

未完待续。。。

关于字符串精确匹配

标签:

原文地址:http://www.cnblogs.com/ykzou/p/5840729.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!