字元匹配問題(1) Rabin Karp演算法

2021-08-29 19:07:37 字數 1829 閱讀 6235

字串匹配問題(1)——rabin-karp演算法

1.問題描述

給定目標字串 t[0..n-1] (基於 0 的陣列,陣列長度為 n ),和模式串 p[0..m-1] ,問 p 可否匹配 t 中的任意子串,如果可以,返回匹配位置。

2.問題分析

直觀分析

brute-force 的蠻力法,適用於較小規模的字串匹配。

優化

主要介紹 3 種優化辦法,分別具體為: rabin-karp 演算法,有限自動機和 kmp 演算法。將分為 3 篇博文分別討論。本小節主要介紹 rabin-karp 演算法。

得出演算法

rabin-karp 演算法(以下簡稱為 rk 演算法),是基於這樣的思路:即把串看作是字符集長度進製的數,由數的比較得出字串的比較結果。例如,給定字符集為∑ = ,∑長度為 d=10 ,那麼任何以∑為字符集的串都可看作 d (此處為 10 )進製的數。

記模式串 p[0..n-1] 對應的數值為 p , t[0..n-1] 所有長度為 m 的子串對應的數值為 ts

,設 p 和 t 都是基於字符集長度為 | ∑ |=d 的字串。

那麼, ts

即為 t[s..s+m] 對應的數值,這裡 0<=s<=n-m-1 。

p = p[m]+d*(p[m-1]+d*(p[m-2]+..)))

同樣 t0

也可類似求得。

最重要的是如何從 ts

求出 ts+1

。 ts+1 =t[s+m]+d*(ts +dm-1 *t[s])

注:此處是該演算法的關鍵,即在常數時間內能夠計算出下乙個 m 長度的字串對應的數值。初看比較抽象,舉個例子就比較明白了,設 x=12345 ,現在是已知長度為 3 的數值 234 ,現在要求 345 對應的數值,可以這樣來得到: 345 = 5 + 10*(234-102 *2)

3.演算法描述

求出所有 m 長度子串所對應的數值,對數值進行比較,繼而得出子串是否匹配。當模式串長度很大時,這時對應的數值會很大,比較起來比較麻煩,可使用對乙個大奇數取模後進行比較。

4.具體實現

這裡實現的只是m值較小時的情形,大整數需要特定的類的支援(如可自定義大整數類),選取10進製的數是為了方便起見,當然字母也是ok的。

#include "iostream"

#include "string"

#include "cmath"

using namespace std;

// get the value of the character in the set

int getv(char p, string set)

{ for(int i=0; i5.參考資料

[1]   thomas h. cormen introduction to algorithms

字串匹配問題

在字串匹配問題中,我們期待察看串t中是否含有串p。其中串t被稱為目標串,串s被稱為模式串。進行字串匹配,最簡單的乙個想法是 public class match 可以看見,這個演算法 假定m n 的複雜度是o mn 其中m是t的長度,n是p的長度。這種演算法的缺陷是匹配過程中帶有回溯 準確地說是t串...

字串匹配問題

給出乙個字串和多行文字,在這些文字中找到字串出現的那些行。你的程式還需支援大小寫敏感選項 當選項開啟時,表示同乙個字母的大寫和小寫看作不同的字元 當選項關閉時,表示同乙個字母的大寫和小寫看作相同的字元。輸入輸入的第一行包含乙個字串s,由大小寫英文本母組成。第二行包含乙個數字,表示大小寫敏感的選項,當...

字串匹配問題

字串中只含有括號 判斷輸入的字串中括號是否匹配。如果括號有互相包含的形式,從內到外必須是 例如。輸入 輸出 yes,而輸入 都應該輸出no。第一行為乙個整數n,表示以下有多少個由括好組成的字串。接下來的n行,每行都是乙個由括號組成的長度不超過255的字串 在輸出中有n行,每行都是yes或no。5 y...