算法-字符串匹配(String Matching)-(1)-朴素匹配和Rabin-Karp算法

题目:算法-字符串匹配(String Matching)-(1)-朴素匹配和Rabin-Karp算法

摘要:
此文介绍了字符串匹配算法以及基本分析,最后总结。
此系列文均为方便日后重复粗略查看时不必翻看书籍。
 
简要介绍
字符串匹配是比较普遍的一个算法问题。一般设字符串T[1..n],以及模式串P(1..m], m<=n,模式串P首次出现在T中的位置,
或者所有在T中出现的位置。
所谓在T中s位置出现,即T[s+1..s+m]=P[1..m]
 
本文将主要参考算法导论以及算法分析导论中的相关内容,介绍朴素的字符串匹配算法,Rabin-Karp算法。
利用有限自动机进行字符串匹配,Knuth-Morris-Pratt算法以及triet树将在以后其他文中介绍
基本上都是书上内容的重复,但是使用更少的文字以及自己容易理解的语言。
1. 朴素的字符串匹配算法(The naive string-matching algorithm)
该算法可以形象的看成用一个包含模式的模板沿着文本滑动,同时进行进行字符比较。
下面算法过程是[2]P559 给出的算法过程。
NAIVE-STRING-MATCHER(T, P)
1 nlength[T]
2 mlength[P]
3 for s ← 0 to n - m
4     do if P[1 ‥ m] = T[s + 1 ‥ s + m]
5           then print "Pattern occurs with shift" s
 
下图把模板滑动过程作了比较形象的表现。
 
该算法中,模板将滑动 n-m +1次,每次滑动一个位置后的匹配最多将比较m次。因此最坏情况下运行时间为 thet[ (n-m+1) * m ]
可以看出,本算法所采用的方式非常的简单直观。
显然这种算法效率不高,为什么呢?
因为该算法中将每次s比较的结果都认为是相互独立的,但可能其中的信息对下次比较用处很大。例如 if P
 = aaab and we find that s
 = 0 is valid, then none of the shifts 1, 2, or 3 are valid, since T
 [4] = b.
接下来介绍的几种算法将通过参考每次扫描匹配信息而增强算法的效率。
2. Rabin-Karp算法
Rabin-Karp算法就是Rabin和Karp这俩哥们建议的算法啦。
这个算法引入了一个重要的idea:把P[1..m]中的每一个字符都当作X进制的一个数字(X你自己琢磨用多少吧),然后把这些数
(注意,不是字符啦)按位(注意,是按位相加,不是直接相加)相加,其和记为p.
然后把T中的各种连续m个数都相加,如果其与P各数之和相等,则认为匹配。设 t(i) 表示 T[i+1…i+m]按位相加之和
*按位相加:举个例子 P中数字 [4,5,6,3,8] 均为10进制(10进制简单些,举例而已),
那么按位相加 8+30 + 600+ 5000+ 40000 = 45638.
 
预处理的简化:
计算t(i) i=0,..n-m的过程定义为预处理
要使用这个算法,还要将T中的所有的可能的ti,共 n-m+1个,每次计算需要 fai(m)时间。这样只是预处理就要 
thet( (n-m+1)*m)时间,
是无法让人接受的。
这里介绍一种可以在thet(n-m)时间内计算出剩余ti值的公式  t(s+1) = 10 ( t(s) – 10的m-1次幂*T[s+1] ) + T[s+m+1]。
  则总的时间为 thet(n-m+1)。
 
预处理的另外一只问题:
计算t(i)不得不面对一个非常现实的问题,就是p 和t(i)的值可能非常大。如此大的数做算术操作,其时间必然不能再认为是常数了。
我们通过取模(mod)的方式,降低这个p, t(i)计算级。这样降低了计算的复杂度,但是增加了 伪命中的概率。
但是,只要取模的数字选的好些,对各个命中点都重新进行一次全匹配,也可以解决问题。
 
下面给出[2] P562对该算法的计算过程
RABIN-KARP-MATCHER(T, P, d, q)
 1 nlength[T]
 2 mlength[P]
 3 hdm-1 mod q
 4 p ← 0
 5 t0 ← 0
 6 for i ← 1 to m           ▹ Preprocessing.
 7     do p ← (dp + P[i]) mod q
 8        t0 ← (dt0 + T[i]) mod q
 9 for s ← 0 to n - m       ▹ Matching.
10     do if p = ts
11           then if P[1 ‥ m] = T [s + 1 ‥ s + m]
12                   then print "Pattern occurs with shift" s
13        if s < n - m
14           then ts+1 ← (d(ts - T[s + 1]h) + T[s + m + 1]) mod q

 

 
[1]算法分析导论
[2]算法导论
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值