子字串查詢之Rabin Karp演算法

2022-04-07 05:24:58 字數 1747 閱讀 8917

1.1 演算法簡介:m.o.rabin和r.a.karp發明了一種基於雜湊的字串查詢演算法。我們只需要計算模式串的雜湊函式,然後利用相同的雜湊函式計算文字中所有可能的m個字元的子字串雜湊值並尋找匹配。如果找到了乙個雜湊值和模式字串相同的子字串,再繼續驗證是否相同。這是乙個有趣的演算法,重點不在於其只用線性時間解決問題,而在於其對雜湊技術的使用,這是乙個具有啟發性的演算法!

1.2 結論:rabin-karp演算法優點是執行速度為線性級別,缺點是內迴圈很長。(若干次算術運算,而其他演算法都只需比較字元)

2.1 基本思想:長度為m的模式串對應著乙個r進製的m位數使用除留餘數法構造乙個能夠將 r 進製的 m 位數轉化為乙個0到q-1之間的 int 值的雜湊函式。我們在不溢位的情況下選擇乙個盡可能大的隨機素數q(因為我們並不真正需要一張雜湊表,故q越大越好,衝突越少)。接下來對文字所有長度為m的子串計算雜湊值並尋找匹配。

2.3 關鍵思想:既然子串長度確定為m(即模式串的長度m),那我們每次只需向後移動一位,將第乙個元素去掉,最後乙個元素加上即可更新雜湊值,再與模式串雜湊值比較即可。在這種情況下時間複雜度與n成正比。

3.1 具體步驟:

得到模式串長度m

選擇乙個恰當的r,盡可能大的隨機素數q,構造雜湊函式

計算出模式串的雜湊值pathash

從文字第乙個子串開始,依次向右移動,判斷其雜湊值是否與pathash相等

3.2 利用蒙特卡洛法驗證正確性:在之前我們講過,當雜湊值相同時我們再逐個比較字元是否匹配,以此來確保我們得到的是乙個匹配而非僅僅雜湊值相同的子串,但是我們可以不這麼做。假設我們取乙個1e20數量級的素數q,那麼乙個隨機鍵的雜湊值與模式串衝突的概率就會小於1e-20。這足以確保答案的正確性,如果仍不放心,我們可以再執行一次,這樣就下降到了1e-40,同理你可以將概率降到你滿意的數值(犧牲時間)。

3.3 **示例:

/*

rabin-karp演算法

-valenshi

只能匹配數字,選r為10,若想匹配其他字元,需要調整。

*/ #include#includetypedef long long ll;

const int maxn = 1e5;

const int r = 10;

const int q = 1e9+7;

char pat[maxn],txt[maxn];

int rm;

ll qpow(ll a,ll b,ll m)

return res%m;

}int charvalue(char a,int i)

ll hash(char a,int m)

bool check(int x)

int solve()

return n; //未找到

}int main()

3.4 使用注意:與kmp比起來,這個演算法理解起來簡單一些(如果熟悉雜湊表的話),也有趣一些,但是該演算法需要注意r的選取。如果僅僅匹配數字字串,那麼r大於10皆可,若包括各種字元,我們則需要為每個字元設定乙個r進製的值(可以使用ascii碼),這時要求r要大於字元總數(否則有衝突)。相比之下kmp演算法等其他演算法則沒這方面的缺陷。

查詢 子字串查詢

子字串查詢 子字串查詢的常見方法 暴力破解 sunday和kmp。1 暴力查詢 暴力查詢就是用兩個指標i,j分別指向字串和子字串,如果指標指向的字元相等則兩指標右移 否則,指向字串的指標i回到本次匹配的下乙個位置,而指向匹配字串的指標j回到匹配字串的開頭。public int search stri...

字串 查詢子串

主要的思路就是,不斷的從母串 str1 中取出和子串長度相等的臨時子串 temp str,與子串 str2 進行比較。沒有找到子串,返回 1 成功找到子串,返回子串首字母在母串中的位置,該位置從 0 開始。include include char temp str 30 臨時子串 void read...

sql之 字串的子片段查詢

一.實現方法 1.substring expression start length 返回字元 binary text 或 image 表示式的一部分。expression 字串 二進位制字串 text image 列或包含列的表示式 start 整數,指定子串的開始位置 注 sql中 1 表示字串...