字串匹配演算法 Rabin Karp 演算法

2021-09-08 09:41:15 字數 3220 閱讀 2605

字串匹配演算法 -- rabin-karp 演算法

參考資料

1 演算法導論

2 lalor

3 記憶碎片

在實際應用中,rabin-karp 演算法對字串匹配問題能較好的執行。rabin-karp 演算法需要對字串和模式進行預處理,其預處理時間為 o ( m ) ,在最壞情況下的執行時間為 o ( ( n-m+1 ) m ) ,但基於某種假設(不知道是何種假設),它的平均情況下的執行時間還是比較好的。

為了便於說明,假設 

∑ = ,這樣每個字元都是乙個十進位制數字。(對於更一般的情況,可以假設每個字元都是基數為 d 的表示法中的乙個數字,d = | ∑ | 。)可以用乙個長度為 k 的十進位制數來表示由 k 個連續字元組成的字串。因此,字串31415 就對應於十進位制數 31415 。

已知乙個模式 p[ 1.. m ],設 p 表示該模式所對應的十進位制數的值(如模式 p = "31415" ,數值p = 31415)。對於給定的文字 t [ 1.. n ],用 ts 來表示其長度為 m 的子字串 t [ s+1.. s+m ] (s = 0,1,.. n-m)相對應的十進位制數的值。ts = p 當且僅當 t [ s+1.. s+m ] = p[ 1.. m ] ,因此 s 是有效位移當且僅當 ts = p 。

於是應用霍納法則(horner's rule)在 o ( m ) 的時間內計算 p 的值:

p = p[ m ] + 10( p[ m-1 ] + 10 ( p[ m-2 ] + .. + 10( p[ 2] + p[ 1 ]) ... ))

類似的,也可以在 o ( m ) 時間內根據 t[ 1.. m ] 計算出 t0 的值。

為了在 o ( n - m ) 的時間內計算出剩餘的值 t1,t2,...,t ( n - m ),可以在常數時間內根據 ts 計算出 t ( s+1 )。因為

t ( s + 1) = 10 ( ts - 10^(m-1) t [ s+1 ] ) + t [ s + m +1]             ( 1 )

事實上,就是去掉最高位,然後左移了一位,在加上 t [ s + m +1] ,就得到了 t ( s + 1) 。

預處理的時間為 o ( m )

當進行完預處理之後,就可以執行字串匹配了。我們只需要將 ti ( i = 0 , 1 ,  ...  n-m ) 與 p 進行比較,相等則為合法匹配,否則為非法匹配。整個匹配過程的時間為 o ( n -m + 1 )

然而,上述問題對於模式 p 的長度較小時,比較方便。當 p 和 ts 的值很大時,p 的結果會太大,以至於不能很好的處理這類問題 。所以才有了下面的改進版本。

對乙個合適的模 q 來計算 p 和 ts 的模。每個字元是乙個十進位制數,因為 p ,t0 以及遞迴式 1 計算過程都可以對模 q 進行,所以可以在 o ( m ) 時間內計算出模 q 的 p 值。在時間 o( n-m+1 ) 計算出模 q 的所有 ts 值。通常選模 q 為乙個素數,使得 10q 正好為乙個計算機字長。

在一般情況下,採用 d 進製的字母表 時,所選取的 q 要滿足使 dq 的值在乙個計算機字長內,並調整遞迴式 ( 1 ) 以使對模 q 進行運算,使其成為

t ( s + 1) = ( d ( ts -  t [ s+1 ] h ) + t [ s + m +1]  ) mod q

其中 h 

≡ d ^ ( m-1 ) (mod q) 。

加入模 q 後,我們已經不能通過 ts

≡ p (mod q ) 並不能說明 ts = p 。當 ts

≡ p (mod q ) 不成立時,則肯定 ts != p 。因此,當 ts

≡ p (mod q ) 時我們還需要進一步進行測試,看看 ts 是否等於  p ,因為 ts 可能是匹配的也有可能是偽匹配的。

這個演算法就是有點使用hash的思想了。把模式字串進行乙個預處理,並mod,主字串進行逐個進行簡單的hash對映,然後mod比較。

偽**如下

rabin-karp-matcher( t,p,d,q)

1 n ← length[ t ]

2 m ← length[ p]

3 h ← d^(m-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 s-m matching( 匹配 )

10 do if p = t

11 then if p[1..m] = t[s+1..s+m] 對p 和 t 中的每個字元進行判斷

12 then print "匹配"

13 if s < n - m

14 then t(s+1) ← (d (ts - t[s+1] h) + t[s+m+1]) mod q

**實現 *

*authored by laimingxing on: 2023年 03月 04日 星期日 18:18:28 cst

* * @desc:

* * @history

*/

// d = 256 ; q = 127

void rabin_karp_matcher( char *t, char *p, int q)

//slide the pattern over text one by one

for( i = 0; i <= n - m; i++)

//caluate hash value for next window of test:remove leading digit,

//add trailling digit

if( i < n - m )

} }

rabin-karp-matcher 的預處理時間為 o ( m ) ,其匹配時間在最壞情況下為 o ( ( n- m + 1) m) ,

雖然 rabin-karp-matcher 在最壞的情況下與樸素匹配一樣,但是實際應用中往往比樸素演算法快很多,應用還是很廣的。

字串匹配演算法 字串匹配演算法總覽

字串匹配在文字處理裡非常重要,我們採用簡潔的python 把以下演算法一一實現並講解。樸素演算法 algorithm rabin karp 演算法 有限自動機演算法 finite automation knuth morris pratt 演算法 kmp algorithm boyer moore ...

字串匹配演算法

首先引用一下另一篇文章中對字串匹配的介紹 字串匹配指的是從文字中找出給定字串 稱為模式 的乙個或所有出現的位置。本文的演算法一律輸出全部的匹配位 置。模式串在 中用x m 來表示,文字用y n 來,而所有字串都構造自乙個有限集的字母表 其大小為 根 據先給出模式還是先給出文字,字串匹配分為兩類方法 ...

字串匹配演算法

平常操作文字的時候,經常需要操作對字串進行操作。而字串中最重要的一種操作就叫匹配,字串的匹配演算法很多,人們最熟悉的莫過於kmp演算法了。今天就來談一談一些字串匹配演算法。先來說說大名鼎鼎的kmp演算法,這個演算法出現在無數的資料結構與演算法書上面。它的策略很簡單 當模式串第k個字元不匹配主串中第s...