現要匹配兩字串的相同內容:
第一輪:
我們從主串的首位開始,把主串和模式串的字元逐個比較:
顯然,主串的首位字元是a,模式串的首位字元是b,兩者並不匹配。
第二輪:
我們把模式串後移一位,從主串的第二位開始,把主串和模式串的字元逐個比較:
主串的第二位字元是b,模式串的第二位字元也是b,兩者匹配,繼續比較:
主串的第三位字元是b,模式串的第三位字元也是c,兩者並不匹配。
第三輪:
我們把模式串再次後移一位,從主串的第三位開始,把主串和模式串的字元逐個比較:
主串的第三位字元是b,模式串的第三位字元也是b,兩者匹配,繼續比較:
主串的第四位字元是c,模式串的第四位字元也是c,兩者匹配,繼續比較:
主串的第五位字元是e,模式串的第五位字元也是e,兩者匹配,比較完成!
由此得到結果,模式串 bce 是主串 abbcefgh 的子串,在主串第一次出現的位置下標是 2:
這個演算法有乙個名字,叫做bf演算法,是brute force(暴力演算法)的縮寫。
但是!遇到下面的情況就會很麻煩
所以我們就有了rk演算法!(rabin-karp兩位發明者)通過雜湊值來檢索
比較雜湊值是什麼意思呢?
用過雜湊表的朋友們都知道,每乙個字串都可以通過某種雜湊演算法,轉換成乙個整型數,這個整型數就是hashcode:
hashcode = hash(string)
顯然,相對於逐個字元比較兩個字串,僅比較兩個字串的hashcode要容易得多。
第一步,我們需要生成模式串的hashcode。
生成hashcode的演算法多種多樣,比如:
按位相加
這是最簡單的方法,我們可以把a當做1,b當做2,c當做3…然後把字串的所有字元相加,相加結果就是它的hashcode。
bce = 2 + 3 + 5 = 10
但是,這個演算法雖然簡單,卻很可能產生hash衝突,比如bce、bec、cbe的hashcode是一樣的。
轉換成26進製數
既然字串只包含26個小寫字母,那麼我們可以把每乙個字串當成乙個26進製數來計算。
bce = 2*(26^2) + 3*26 + 5 = 1435
這樣做的好處是大幅減少了hash衝突,缺點是計算量較大,而且有可能出現超出整型範圍的情況,需要對計算結果進行取模。
為了方便演示,後續我們採用的是按位相加的hash演算法,所以bce的hashcode是10:
第二步,生成主串當中第乙個等長子串的hashcode。
由於主串通常要長於模式串,把整個主串轉化成hashcode是沒有意義的,只有比較主串當中和模式串等長的子串才有意義。
因此,我們首先生成主串中第乙個和模式串等長的子串hashcode,
即abb = 1 + 2 + 2 = 5:
第三步,比較兩個hashcode。
顯然,5!=10,說明模式串和第乙個子串不匹配,我們繼續下一輪比較。
第四步,生成主串當中第二個等長子串的hashcode。
bbc = 2 + 2 + 3 = 7:
第五步,比較兩個hashcode。
顯然,7!=10,說明模式串和第二個子串不匹配,我們繼續下一輪比較。
第六步,生成主串當中第三個等長子串的hashcode。
bce= 2 + 3 + 5 = 10:
第七步,比較兩個hashcode。
顯然,10 ==10,兩個hash值相等!這是否說明兩個字串也相等呢?
別高興的太早,由於存在hash衝突的可能,我們還需要進一步驗證。
第八步,逐個字元比較兩字串。
hashcode的比較只是初步驗證,之後我們還需要像bf演算法那樣,對兩個字串逐個字元比較,最終判斷出兩個字串匹配。
最後得出結論,模式串bce是主串abbcefgh的子串,第一次出現的下標是2。
關鍵問題又來了:每次hash的時間複雜度是o(n),如果把全部子串都進行hash,總的時間複雜度豈不是和bf演算法一樣,都是o(mn)?解決方法如下:
上圖中,我已知子串abbcefg的hashcode是26,那麼如何計算下乙個子串,也就是bbcefgd的hashcode呢?
我們沒有必要把子串的字元重新進行累加運算,而是可以採用乙個更簡單的方法。由於新子串的前面少了乙個a,後面多了乙個d,所以:
新hashcode = 舊hashcode - 1 + 4 = 26-1+4 = 29
新hashcode = 舊hashcode - 2 + 5 = 29-2+5 = 32
**如下:
public
static
intrabinkarp
(string str, string pattern)
//如果不是最後一輪,更新主串從i到i+n的hash值
if(i
}return-1
;}private
static
inthash
(string str)
return hashcode;
}private
static
intnexthash
(string str,
int hash,
int index,
int n)
private
static
boolean
comparestring
(int i, string str, string pattern)
public
static
void
main
(string[
] args)
參考文件 字串 什麼是字串匹配演算法?
字串 string 是由 n 個字元組成的乙個有序整體 n 0 例如,s beijing s 代表這個串的串名,beijing 是串的值。這裡的雙引號不是串的值,作用只是為了將串和其他結構區分開。字串的邏輯結構和線性表很相似,不同之處在於字串針對的是字符集,也就是字串中的元素都是字元,線性表則沒有這...
字串匹配演算法 字串匹配演算法總覽
字串匹配在文字處理裡非常重要,我們採用簡潔的python 把以下演算法一一實現並講解。樸素演算法 algorithm rabin karp 演算法 有限自動機演算法 finite automation knuth morris pratt 演算法 kmp algorithm boyer moore ...
字串匹配演算法
首先引用一下另一篇文章中對字串匹配的介紹 字串匹配指的是從文字中找出給定字串 稱為模式 的乙個或所有出現的位置。本文的演算法一律輸出全部的匹配位 置。模式串在 中用x m 來表示,文字用y n 來,而所有字串都構造自乙個有限集的字母表 其大小為 根 據先給出模式還是先給出文字,字串匹配分為兩類方法 ...