字串 Rabin Karp指紋字串查詢演算法

2021-07-16 07:11:32 字數 3027 閱讀 4657

暴力字串匹配(brute force string matching)是子串匹配演算法中最基本的一種,它確實有自己的優點,比如它並不需要對文字(text)或模式串(pattern)進行預處理。然而它最大的問題就是執行速度太慢,所以在很多場合下暴力字串匹配演算法並不是那麼有用。我們需要一些更快的方法來完成模式匹配的工作,然而在此之前,我們還是回過頭來再看一遍暴力法匹配,以便更好地理解其他子串匹配演算法。

如下圖所示,在暴力字串匹配裡,我們將文字中的每乙個字元和模式串的第乙個字元進行比對。一旦我們找到了乙個匹配,我們就將文字中寫乙個字元取出來和模式串的第二個字元進行比較。

暴力字串匹配之所以慢,是因為它需要比對文字和模式串的每個字元

該演算法執行速度慢的主要原因有二:一方面,我們需要對文字中的每個字元都進行比對;另一方面,即使我們發現模式串首字元和文字中的某個字元相匹配,我們仍然需要對模式串中剩下的所有符號(字元)挨個進行比對,才知道它們是不是出現在接下來的文字中。那麼,是否有別的方法可以用來判斷文字是否包含模式串呢?

答案是肯定的,確實存在一種更快的方法。為了避免挨個字元對文字和模式串進行比較,我們可以嘗試一次性判斷兩者是否相等。因此,我們需要乙個好的雜湊函式(hash function)。通過雜湊函式,我們可以算出模式串的雜湊值,然後將它和文字中的子串的雜湊值進行比較。這裡有乙個問題,我們必須保證該雜湊函式能夠對乙個較長的字串返回較短的雜湊值。然而,我們又不能指望較長的模式串能得到較短的雜湊值。但除此之外,這個新方法在速度上應該能比暴力法有顯著提公升。

這種更快的方法就是rabin-karp演算法。

michael o. rabin和richard m. karp在2023年提出乙個想法,即可以對模式串進行雜湊運算並將其雜湊值與文字中子串的雜湊值進行比對。總的來說這一想法非常淺顯,唯一的問題在於我們需要找到乙個雜湊函式 ,它需要能夠對不同的字串返回不同的雜湊值。例如,該雜湊函式可能會對每個字元的ascii碼進行算,但同時我們也需要仔細考慮對多語種文字的支援。

雜湊演算法可以有很多種不同的形式,它可能包含ascii碼字元以便對數字進行轉化,但也可能是別的形式。我們唯一需要的就是將乙個字串(模式串)轉化成為能夠快速進行比較的雜湊值。以"hello world"為例,假設它的雜湊值hash('hello world')=12345。那麼如果hash('he')=1,那麼我們就可以說模式串"he"包含在文字"hello world"中。由此,我們可以每次從文字中取出長度為m(m為模式串的長度)的子串,然後將該子串進行雜湊,並將其雜湊值與模式串的雜湊值進行比較。

我們已經看了一些關於rabin-karp演算法的**,現在讓我們來關注一下它的實現。以下的php**展示了通過乙個簡單的雜湊表來將字元轉化成整數的例項。它非常簡單,僅僅只是為了用來闡明rabin-karp演算法的基本原理。

function

hash_string

($str

,$len)];

}return

(int

)$hash;}

function

rabin_karp

($text

,$pattern

)$text_hash

=hash_string

(substr

($text,$i

,$m),$m);}

return-1

;}// 2

echo rabin_karp

('hello world'

,'ello'

);

rabin-karp演算法非常適用於多模式匹配(multiple pattern match)。事實上,它天生就是能夠支援此類的操作,這也是它相對於其他字串查詢演算法的優勢。

rabin-karp演算法的複雜度是o(nm),其中n和m分別是文字和模式串的長度。那麼它到底比暴力匹配好在哪兒呢?暴力匹配法的演算法複雜度同樣是o(nm),這樣看起來rabin-karp演算法在效能上並沒有多大提公升。然後在實際使用過程中,rabin-karp的複雜度通常被認為是o(n+m)。這就使得它比暴力匹配法要快一些,具體見下圖。

rabin-karp的複雜度理論上是o(nm),但在實際使用中通常是o(n+m)

需要注意的是rabin-karp演算法需要o(m)的預處理時間。

譯者注:事實上,由於雜湊函式無法保證對不同的字串產生不同的雜湊值,有雜湊衝突的現象存在,所以即使模式串的雜湊值和文字子串的雜湊值相等,也需要對這兩個長度為m的字串進行額外的比對(當然,如果不相等也就不用比對了,其實大部分的時間省在這上面),這時比對的開銷是o(m)。最壞情況下,文字中所有長度為m的子串(一共n-m+1個)都和模式串匹配,所以演算法複雜度為o((n-m+1)m)。然而實際情況下,需要進一步比對的子串個數總是有限的(假設為c個),那麼演算法的期望匹配時間就變成o((n-m+1)+cm)=o(n+m)。

我們已經看到rabin-karp演算法比暴力匹配法其實也快不了太多,那它的應用場景到底是**?

譯者注:原文沒有給出具體答案。要回答這個問題,需要先了解rabin-karp演算法被稱道和詬病的原因。然後根據自己的具體應用需要來做判斷。

它可以用來檢測抄襲,因為它能夠處理多模式匹配;

雖然在理論上並不比暴力匹配法更優,但在實際應用中它的複雜度僅為o(n+m);

如果能夠選擇乙個好的雜湊函式,它的效率將會很高,而且也易於實現。

有許多字串匹配演算法的複雜度小於o(n+m);

有時候它和暴力匹配法一樣慢,並且它需要額外空間。

computer algorithms: morris-pratt string searching

computer algorithms: boyer-moore string searching

computer algorithms: brute force string matching

**暴力字串匹配(含js實現示例)——計算機演算法系列

4042 Rabin Karp字串匹配

時間限制 1000ms 記憶體限制 65536kb 描述現在有乙個僅由小寫字母組成的字串s,假定將字母a,b,c.z依次編號為1,2,3.26,現在要在s中找到所有長度為m的且字母編號和為q的子串。輸入第一行輸入n,表示測試資料的個數,以下n行每行包含乙個測試資料 一行測試資料由三部分組成 字串s ...

(三)Rabin Karp字串查詢演算法

不同於傳統的字元比較,本演算法的核心在於雜湊。先計算出子串 pat 的乙個雜湊值,然後從文字 txt 中,從 i 0 開始,計算從當前 i 開始的子串長度的字串的雜湊,比如 pat 250 txt 230240250 計算的是 230 302 024 的雜湊,依次類推,與 250 的雜湊值進行比較,...

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

字串匹配演算法 rabin karp 演算法 參考資料 1 演算法導論 2 lalor 3 記憶碎片 在實際應用中,rabin karp 演算法對字串匹配問題能較好的執行。rabin karp 演算法需要對字串和模式進行預處理,其預處理時間為 o m 在最壞情況下的執行時間為 o n m 1 m 但...