【算法notes】String Matching(算法导论ch32)

应用:word编辑器里查找某个特定word的功能;DNA序列里查特定pattern。

各种时间复杂度

m是pattern的长度,n是text的长度。

上面RK的matching时间是worst case,有点坑,但average case其实挺快的。

解决模式:沿着text T滑动pattern P, 用shift S来记录相对位移。

1. Naive的方法,是把s所有的值对应的情况都检查了一边,没有preprocess。之所以不够高效,是因为在处理shift = s+1时没有用上shift =s得到的信息。

2.Rabin-Karp-Matcher:

所有的character都对应成基数为d的digits(radix-d, d = 所用字母表的大小)。

把string P处理成integer p, 把shift = s时T上长度为m的子串处理成t(s),而且在t(s)的基础上计算t(s+1)。

这样preprocess的时间是Theta(m)。

处理成integer的问题:数太大了放不下 ==>那就把p和t(s)都mod q。 

如果p mod q = t(s) mod q,那再进一步检查是不是p = t(s),否则肯定是p不等于t(s),叫spurious hit。

因为RK每个s的值都检查了,所以有(n-m+1)个loop,如果每个loop是spurious hit要继续深入检查,那就是O((n-m+1)*m)。

不然在valid hit比较少的情况下,average和expected time还是不错的,spurious hit发生的概率也是和q有关的。

RKMatcher

3. Finite Automata有限自动机

自动机主要抓住,state(当前状态,即match了pattern的前多少个character)

和transition function(状态转移函数)这两个概念。

如果pattern的长度是m, 那么就有[0,...,m]共m+1个状态,其中0是初始状态,

m是accepting状态,表示pattern的每个character都已经匹配了。

转移函数theta(q,a) = sigma(Pq+"a"),其中q是当前的状态,如果此时input是a,那么找到一个string, 

它是(P的前q位加上a)的后缀,同时也是P最长的前缀。

这个string的长度就是theta(q,a),也就是q要转移到的新状态。

当然如果P(q+1)也是a, 那么theta(q,a) = q+1(在还没有被accept的情况下)。

获得这个转移函数的过程就是preprocess的过程,如果有了的话,怎么用呢?

FAMatcher

matching的时间负责度也就是Theta(n)。那preprocess的复杂度咋样呢?

FAGenerator

外面的loop是O(m*|Sigma|),里面可是O(m^2),当然可以优化,到O(m*|Sgima|) overall。


4.KMP(好激动,终于到了看毛片算法)

看毛片算法的主要精髓是:认清了问题的主要矛盾是pattern和自己的match。

在对text按位向后扫的时候,如果当前已经match的位数是k(k<m),那么这个T[s+1,...s+k],也就是目前T的suffix是确定的,就是pattern的前k位。

举个例子,如果T是;abcdfxxxxxx; P是:abcde。那我们在 k = 4,s=0的时候已经知道,如果k+1位match失败,s=1,2,3,4肯定是invalid。

所以我们要做的是,找到pattern的prefix function. 这个function可以分分钟生成有限状态机的转移矩阵的。

prefix function

有了这个函数,我们可以recursive的找到valid的shift cases.

PFGeneration

然后利用这个函数再次来扫Text, 就是KMP算法啦。

KMP

还有最后一个任务,就是KMP的算法复杂度分析。这里是用aggregate的方法。

先说prefix函数生成函数的复杂度,KMP的复杂度同理。

k从0起步,并一直保持小于m(根据prefix函数的定义),所以最大也就是m-1啦,increment总共的次数是O(m).

同时while循环的条件又保证了,k是non-negative的,所以k = pi(k)这种decrement函数,总共执行的次数也是O(m).

所以preprocess的时间复杂度就是O(m).


TBC:KMP和trie结合的AC自动机.


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值