• 算法导论笔记:32字符串匹配算法


           在编辑文本程序中,经常需要在文本中找到某个模式的所有出现位置。典型的情况是:在一个文本文件中,搜索用户输入的关键字。解决这种问题的算法叫做字符串匹配算法。字符串匹配算法的形式化定义如下:假设文本是长度为n的数组T[1..n],而模式是一个长度为m的数组P[1..m],其中m<=n,P和T中的元素都来自有限字符集。比如∑ = {0,1}或者 ={a,b,...z}。字符数组P和T通常称为字符串。

           如果0<=s<=n-m,并且T[s+1..s+m] = P[1..m],则称模式P在文本T中出现,且偏移为s(意味着模式P在文本T中出现的位置是从s+1开始的)。称s为有效偏移。字符串匹配问题就是找到所有的有效偏移。

           字符串x的长度用|x|表示,两个字符串x和y的连接用xy表示,长度为|x|+|y|。如果x=wy,则称字符串w是字符串x的前缀,记做wx。类似的,如果x=yw,则称w是x的后缀,记做wx。例如ab, ccaabcca。的性质如下:

           当且仅当xaya时,有xy;

           如果x,  y,如果|x|<=|y|,那么xy; 如果|x|>=|y|,那么yx;如果|x| = |y|,那么x=y。

     

    一:朴素字符串匹配算法

           朴素字符串匹配算法是通过一个循环找到所有有效偏移,代码如下:

           NAIVE-STRING-MATCHER(T, P)

                  n= T.length

                  m=P.length

                  for s = 0 to n-m

                         if P[1..m] == T[s+1, s+m]

                                print “Patternoccurs with shift” s

           在最坏情况下, 朴素字符串匹配算法运行时间为O((n-m+1)m)。这种朴素算法的效率不高,是因为当其他无效s值存在时,它也只关心一个有效的s值,而完全忽略了检测无效s值时获得的文本信息。而这些信息可能很有用。

     

    二:Rabin-Karp算法

           Rabin-Karp算法的预处理时间是O(m),最坏情况下,运行时间为O((n-m+1)m)。但是平均情况下,它的运行时间还是比较好的。

           假设={0,1,2,...9},这样每个字符都是十进制数字。因而可以用长度为k的十进制数表示由k个连续的字符组成的字符串,比如字符串“31415”对应着十进制数31415。

           给定一个模式P=[1..m],假设p表示其相应的十进制数,给定文本T[1..n],假设表示T[s+1..s+m]所对应的十进制数,其中s=0,1,...,n-m。可以在O(m)时间计算出p,比如:


    计算也类似。

           可以在时间O(n-m)内计算出剩余的...可以根据计算出

           所以,总时间为O(m) + O(n-m) = O(n)的时间。

           以上的结论是针对p的值不太大的情况,若P包含m个字符,m比较大,则p上的每次算数运算需要“常数”时间这一假设就不合理了。利用素数可以容易的解决该问题:选取一个素数q,计算p和模q的值,就可以在O(m)时间内计算出模q的p和的值。这样,上面的式子就变为:

          

    其中h(mod q)。上面的式子以及下面的程序之所以成立,是基于下面的等式:

           若c=a+b, 则c mod q = (a mod q + b mod q) mod q。

           但是基于模q的结果并不是完全正确的,(mod q)并不能完全说明p = 。但是如果p != (mod q),则一定可以断定p != 所以,任何满足(mod q)的偏移s都需要进一步检测,看s是真的有效偏移,还是一个伪命中点。如果q足够大,则这个伪命中点就能尽量少的出现。代码如下:

           

           RABIN-KARP算法的预处理时间是O(m),最坏情况下,它的匹配时间是O((n-m+1)m),比如n-m+1个可能的偏移中每一个都是有效的。

           在实际的应用中,因为任意的模q的余数等于p的概率为1/q,所以预计伪命中的次数为O(n/q),每次命中的时间代价是O(m),所以该算法的期望运行时间是:O(n) + O(m(v + n/q)),其中v是有效偏移,如果v = O(1)并且q>=m, 则算法的运行时间为O(n)。

     

    三:利用有限自动机进行字符串匹配

           一个有限自动机M是一个五元组(Q,, A,,δ),其中:

           Q是状态的有限集合;

           是初始状态;

           A是可以接受状态集合;

           是输入字符集

           δ是状态转换函数,如果有限自动机在状态q读入字符a,则它的状态从q转换为δ(q, a)。即进行了一次状态转移。如果当前状态q属于A时,就说自动机M接受了迄今为止读入的字符串。

           在有限自动机M中,引入终态函数Φ,Φ(w)是在扫描完字符串w后的状态。递归定义函数如下:

     

           对于给定的模式P,可以在预处理阶段构造出一个字符串匹配自动机,为了说明与给定模式P[1..m]对应的字符串匹配自动机,首先定义辅助函数σ,称为对应P的后缀函数。满足:σ(x) =max{k:}也就是P的前缀字符串同时满足又是x的后缀字符串中,k的最大取值。例如对于模式P=ab, 有σ(ε) = 0,σ(ccaca)=1,σ(ccab)=2。

           对于长度为m的模式Pσ(x)=m,当且仅当

           如果x,则 σ(x)<=σ(y).

     

           对于给定模式P[1..m],其相应的有限自动机M定义如下:

           状态集合Q={12.., m}。开始状态=0,并且只有状态m是唯一被接受的状态。对任意的状态q和字符a,转移函数δ定义如下:δ(q, a) =

           根据上面的定义,可以得到结论 =,下面证明之:

    1:对任意字符串x和字符a,σ(xa)<=σ(x)+1

           证明:假设r =σ(xa)。如果r=0,因为σ函数非负,所以成立。假设r>0,如下图:

           根据函数的定义有:a,将a从的末尾去掉后,得到,因为如果x,则σ(x)<=σ(y) ,所以 <=σ(x),所以r-1 <=σ(x),因而得证。

    2:对任意x和字符a,如果σ(x)=q,则σ(xa)=

           证明:根据函数的定义有:,如下图所示,有

    假设r =σ(xa),则a,根据上面的证明有σ(xa)<=σ(x)+1,所以r<=q+1,所以|| <= | |,因为如果x,  y,如果|x|<=|y|,那么xy。所以所以=所以r <=,所以σ(xa) <=

           又因为所以σ(xa) >=,因而得证。

    3:如果T[1..n]是自动机的输入文本,则对i=0,1,...n,有 =

           证明:用归纳法证明,当i=0,

    如果 =,现在证明: =.证明过程如下:

          

           所以: =

    算法代码如下:

           FINITE-AUTOMATON-MATCHER(T, )

                  n = T.length

                  q = 0

                  for i = 1 to n

                         q =δ(q, T[i])

                         if q = m

                                print “Pattern occurs with shift” i-m

           

           COMPUTE-TRANSITION-FUNCTION算法的运行时间为O(),如果能够利用精心计算出的模式P的有关信息,则根据P计算出δ所需要的时间可以改进为O(m∑)。所以,预处理时间可以达到O(m),匹配时间为O(n)。

     

    四:KMP算法

           KMP算法预处理时间为O(m),匹配时间为O(n)。预处理过程主要是根据模式P得到前缀函数的值,具体描述参见《KMP算法》。

  • 相关阅读:
    POJ ACM题分类
    HDU 4438 Hunters (概率 & 期望)
    HDU 1042 N!
    HDU 1073 Online Judge
    PKU 1006 Biorhythms (中国剩余定理 * *)
    HDU 1047 Integer Inquiry
    HDU 2710 Max Factorv (素数模板 & 多种解法)
    HDU A + B Problem II 1002
    第6期(江西省吉安市永丰县)县长手机信箱工作简报(自吹自擂政绩,自圆其说)
    Send mail from ASP.NET using your gmail account
  • 原文地址:https://www.cnblogs.com/gqtcgq/p/7247218.html
Copyright © 2020-2023  润新知