算法-字符串匹配(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]算法導論
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章