字串匹配之RKHash演算法

2021-10-08 06:20:26 字數 2179 閱讀 8429

對於任意乙個串,串中字符集的大小為d,則該串中的任意乙個字元都可以用乙個d+1進製的整數來表示。需要注意的是,這裡是d+1進製,而不是d進製,是因為不能用0來表示任意乙個字元,否則如果該字元組成串的乙個字首,無論字首的長度多少,都不會影響串所對應的整數取值。

rabin-karp演算法,它是字串快速查詢的一種演算法,解決思路是把乙個字串,看作是字符集長度進製的樹,如果是ascii,這個進製就是128,如果是只考慮英文小寫字母,那這個進製就是26,通過數值的比較得出字串的比較結果。

如果我們要在 ascii 字符集範圍內查詢「搜尋詞」,由於 ascii 字符集是0~127一共 128 個字元,那麼 d 就等於 128,比如我們要在字串 「abcdefg」 中查詢 「cde」,那麼我們授信計算模式字串 「cde」的hash指紋:

n=len(「cde」)

d=128

hash(cde)= c_ascii*d^(n-1)+ d_ascii*d^(n-2)+ e_ascii*d^(n-3)

=99*128^2+100*128^1+101*128^0

=1634917

模式字串的hash值計算完之後開始計算源串的hash值,計算方法與上面相同:

hash(abc)= a_ascii*d^(n-1)+ b_ascii*d^(n-2)+ c_ascii*d^(n-3)

=97*128^2+98*128^1+99*128^0

=1601891

其中:hash(a)= a_ascii*d^(n-1) =97*128^2= 1589248

hash(b)= b_ascii*d^(n-1) =98*128^1= 12544

hash(c)= c_ascii*d^(n-1) =99*128^0=99

顯而易見的hash(abc)不等於hash(cde),源串的視窗向後滑動一位計算hash(bcd), hash(bcd)的計算如果還是按照上面的方法的話rabin-karp的時間複雜度和暴力解法一樣也是o(m*n),hash(bcd) 可以看成hash(abc)中去掉hash(a),然後加入hash(d),如此一來就將計算指紋的時間複雜度由o(n)降低到o(1):

hash(bcd)= (hash(abc)- hash(a))*d+ hash(d),這樣就可以繼續比較 「cde」 和 「bcd」 是否匹配,以此類推。

由上面的描述可以推導出更一般的規律如下:

hash( txt[s+1 .. s+m] ) = ( d ( hash( txt[s .. s+m-1]) – txt[s]*h ) + txt[s + m] ) mod q

hash( txt[s .. s+m-1] ) : hash value at shift s .

hash( txt[s+1 .. s+m] ) : hash value at next shift (or shift s +1)

d : number of characters in the alphabet

q : a prime number

h: d^(m-1)

加入模q後,h = h』mod q.對於指紋相同的串還要在進行一次比對校驗,如果q足夠大,碰撞的機率會很少出現。

rabin-karp演算法的思想:

假設子串的長度為m,目標字串的長度為n

計算子串的hash值

計算目標字串中每個長度為m的子串的hash值(共需要計算n-m+1次)

比較hash值

如果hash值不同,字串必然不匹配,如果hash值相同,還需要使用樸素演算法再次判斷

為了快速的計算出目標字串中每乙個子串的hash值,rabin-karp演算法並不是對目標字串的 每乙個長度為m的子串都重新計算hash值,而是在前幾個字串的基礎之上, 計算下乙個子串的 hash值,這就加快了hash之的計算速度,將演算法中的內迴圈的世間複雜度從o(m)將到了o(1)。

**示例:

d取字符集的個數

#define d 256

/* s -> search sequence

t -> target sequence

q -> a prime number

*/void search(char *s, char *t, int q)

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

if (j == m)

}if ( i < n-m )

}}

演算法之 字串匹配演算法

一說到兩個字串匹配,我們很自然就會想到用兩層迴圈來匹配,用這種方式就可以實現乙個字串是否包含另乙個字串了,這種演算法我們稱為 bf演算法。bf演算法,即暴力 brute force 演算法,是普通的模式匹配演算法,bf演算法的思想就是將目標串 s 的第乙個字元與模式串 t 的第乙個字元進行匹配,若相...

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

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

字串匹配演算法之BF vs KMP

最笨的方法bf,暴力匹配,無需多說,最難理解的是kmp演算法,費了好大勁才弄明白。要理解kmp演算法,其實最關鍵的是生成標明下次匹配位置的next陣列。其意義是,如果當前匹配到模式字串的第j個字元是失配,則只需要將j重置為next j 後,繼續向後匹配即可。next j 的值表示p 0.j 1 中最...