字符串匹配问题

字符串匹配问题

  • 开始编辑时间:2022年5月19日
  • 完成撰写时间:

1. 问题描述

在文本T中找到某个模式P出现的所有位置.若 T [ S + 1.. s + m ] = P [ 1.. m ] T[S+1..s+m]=P[1..m] T[S+1..s+m]=P[1..m],则称模式P在文本T中出现,偏移s是有效偏移。

1.1 算法概述

每一个字符串匹配算法:

  • 第一步:基于模式进行预处理
  • 第二步:找到所有有效偏移(匹配)

每个算法的预处理时间和匹配时间如下,总运行时间是预处理时间+匹配时间。

算法预处理时间匹配时间
朴素算法0 O ( ( n − m + 1 ) m ) O((n-m+1)m) O((nm+1)m)
Rabin-Karp Θ ( m ) \Theta(m) Θ(m) O ( ( n − m + 1 ) m ) O((n-m+1)m) O((nm+1)m)
有限自动机算法 O ( m ∣ Σ ∣ ) O(m|\Sigma|) O(mΣ) Θ ( n ) \Theta(n) Θ(n)
Knuth-Morris-Pratt Θ ( m ) \Theta(m) Θ(m) Θ ( n ) \Theta(n) Θ(n)

Σ \Sigma Σ : 字符串中字符的集合

∣ Σ ∣ |\Sigma| Σ : 集合的长度

1.2 相关概念

  1. 连结:字符串x和y的连结用"xy“表示
  2. 前缀:x=wy,则w是x的前缀, w ⊏ x w \sqsubset x wx
  3. 后缀:x=yw,则w是x的后缀, w ⊐ x w \sqsupset x wx
  4. 后缀重叠引理:若x,y均是z的后缀,且 ∣ x ∣ ≤ ∣ y ∣ |x| \le |y| xy,则 x ⊐ y x \sqsupset y xy
  5. 字符串相等判断:假设比较是从左向右进行,并且遇到第一个字符不匹配时终止,则需要 Θ ( t + 1 ) \Theta(t+1) Θ(t+1),其中t是x,y的最长公共前缀长度。

2. 朴素算法

对每一个偏移均进行检测是否相等。直到所有的偏移均检测完成。

NAVIE-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 "Patern occurs with shift" s

该算法最坏情况下运行时间为: O ( ( n − m + 1 ) m ) O((n-m+1)m) O((nm+1)m)。这是因为该算法完全忽略了检测无效偏移s时获得的文本信息。后续算法因利用了此信息,算法效率更高。

2.1 算法导论习题讨论

32.1-1

请添加图片描述

32.1-2

由于模式P中的所有字符都不相同,因此:设P[1…m]和T[s+1…s+m]的公共前缀长度为t。则NAVIE-STRING-MATCHER(T,P)算法中偏移量s每次比较后不进行s+1操作,进行s+t即可达到 O ( n ) O(n) O(n)

32.1-3

分析:循环体进行了(n-m+1)次循环,每次循环需要判断两个长度为m的字符串是否相等。若存在不相等,或完全匹配时终止。例如:第一个字符不相等,则立刻终止。

证明:
令P为单个字符比较匹配的概率,则1-P为失配的概率。 P = d d ∗ d = d − 1 P=\cfrac{d}{d*d}=d^{-1} P=ddd=d1

比较v次数概率比较次数*概率
1 ( 1 − P ) (1-P) (1P)1*(1-P)
2 P ( 1 − P ) P(1-P) P(1P)2P(1-P)
3 P 2 ( 1 − P ) P^{2}(1-P) P2(1P) 3 ( P 2 ( 1 − P ) ) 3(P^{2}(1-P)) 3(P2(1P))
m P m − 1 ( 1 − P ) + P m P^{m-1}(1-P) + P^{m} Pm1(1P)+Pm m ( P m − 1 ( 1 − P ) + P m ) m(P^{m-1}(1-P) + P^{m}) m(Pm1(1P)+Pm)

E = ∑ k = 1 m k P k − 1 ( 1 − P ) + m P m E= \sum_{k=1}^m kP^{k-1}(1-P) + mP^{m} E=k=1mkPk1(1P)+mPm
E = ∑ k = 1 m P m − 1 = 1 − d − m 1 − d − 1 E= \sum_{k=1}^m P^{m-1} = \cfrac{1-d^{-m}}{1-d^{-1}} E=k=1mPm1=1d11dm

f ( x ) = 1 − x − m 1 − x − 1 f(x)=\cfrac{1-x^{-m}}{1-x^{-1}} f(x)=1x11xm,求导可知x>=2时,导数为负,函数在x>=2时单掉递减。而 f ( 2 ) = 2 ( 1 − d − m ) < = 2 f(2)=2(1-d^{-m})<=2 f(2)=2(1dm)<=2.因此得证:朴素算法在字符集 ∑ d \sum_{d} d中的预计比较次数:

( n − m + 1 ) 1 − d − m 1 − d − 1 < 2 ( n − m + 1 ) (n-m+1)\cfrac{1-d^{-m}}{1-d^{-1}}<2(n-m+1) (nm+1)1d11dm<2(nm+1)

由此可知,对于随机字符串,朴素算法的平均效率为 O ( 2 ( n − m + 1 ) ) O(2(n-m+1)) O(2(nm+1))

32.1-4

改造上述朴素算法,将模式按照间隔符进行分割,分割成多个子字符串进行处理,在前一个子字符串匹配后,从文本匹配的下一个位置开始,匹配下一个子字符串。设*表示间隔字符

NAVIE-STRING-MATCHER-GAP(T,P)
n = T.length
m = P.length
p_list = P.split("*")
n_start = 0
for p_t in p_list:
    p_m = p_t.length
    for s = n_start to n-p_m:
        if p_t[1..p_m] == T[n_start+1..n_start+p_m]
            n_start += s+1
        else:
            return false
return true
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值