什麼是字串匹配演算法?

2021-10-03 01:17:14 字數 3795 閱讀 3254

現要匹配兩字串的相同內容:

第一輪:

我們從主串的首位開始,把主串和模式串的字元逐個比較:

顯然,主串的首位字元是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 來,而所有字串都構造自乙個有限集的字母表 其大小為 根 據先給出模式還是先給出文字,字串匹配分為兩類方法 ...