資料結構和演算法之美 32 字串匹配演算法

2021-10-11 01:58:07 字數 1567 閱讀 9728

單模式串匹配的演算法,也就是乙個串跟乙個串進行匹配。包括bf演算法rk演算法

也就是在乙個串中同時查詢多個串,它們分別是trie 樹ac 自動機

bf 演算法是最簡單、粗暴的字串匹配演算法,它的實現思路是,拿模式串與主串中是所有子串匹配,看是否有能匹配的子串。所以,時間複雜度也比較高,是 o(n*m),n、m 表示主串和模式串的長度。不過,在實際的軟體開發中,因為這種演算法實現簡單,對於處理小規模的字串匹配很好用

我們每次都比對 m 個字元,要比對 n-m+1 次,所以,這種演算法的最壞情況時間複雜度是 o(n*m)。

rk 演算法是借助雜湊演算法對 bf 演算法進行改造,即對每個子串分別求雜湊值,然後拿子串的雜湊值與模式串的雜湊值比較,減少了比較的時間。所以,理想情況下,rk 演算法的時間複雜度是 o(n),跟 bf 演算法相比,效率提高了很多。不過這樣的效率取決於雜湊演算法的設計方法,如果存在衝突的情況下,時間複雜度可能會退化。極端情況下,雜湊演算法大量衝突,時間複雜度就退化為 o(n*m)。

我們假設要匹配的字串的字符集中只包含 k 個字元,我們可以用乙個 k 進製數來表示乙個子串,這個 k 進製數轉化成十進位制數,作為子串的雜湊值。

這種雜湊演算法有乙個特點,在主串中,相鄰兩個子串的雜湊值的計算公式有一定關係。

從這裡例子中,我們很容易就能得出這樣的規律:相鄰兩個子串 s[i-1]和 s[i](i 表示子串在主串中的起始位置,子串的長度都為 m),對應的雜湊值計算公式有交集,也就是說,我們可以使用 s[i-1]的雜湊值很快的計算出 s[i]的雜湊值。如果用公式表示的話,就是下面這個樣子:

不過,這裡有乙個小細節需要注意,那就是 26^(m-1) 這部分的計算,我們可以通過查表的方法來提高效率。我們事先計算好 260、261、262……26(m-1),並且儲存在乙個長度為 m 的陣列中,公式中的「次方」就對應陣列的下標。當我們需要計算 26 的 x 次方的時候,就可以從陣列的下標為 x 的位置取值,直接使用,省去了計算的時間。

整個 rk 演算法包含兩部分,計算子串雜湊值和模式串雜湊值與子串雜湊值之間的比較。第一部分,我們前面也分析了,可以通過設計特殊的雜湊演算法,只需要掃瞄一遍主串就能計算出所有子串的雜湊值了,所以這部分的時間複雜度是 o(n)。模式串雜湊值與每個子串雜湊值之間的比較的時間複雜度是 o(1),總共需要比較 n-m+1 個子串的雜湊值,所以,這部分的時間複雜度也是 o(n)。所以,rk 演算法整體的時間複雜度就是 o(n)。

當我們發現乙個子串的雜湊值跟模式串的雜湊值相等的時候,我們只需要再對比一下子串和模式串本身就好了。當然,如果子串的雜湊值與模式串的雜湊值不相等,那對應的子串和模式串肯定也是不匹配的,就不需要比對子串和模式串本身了。

資料結構與演算法(32) 字串演算法

檢查字串p是否是字串t的子串。因為要檢查整個定長的字串p,所以有時候這些演算法稱為精確字串匹配演算法。為了便於討論,假設給定的字串t長度為n,要匹配的字串p的長度為m 方法一 蠻力法 思路 檢查text中每乙個可能位置,檢查pattern是否匹配。由於text的長度為n,所以有n m 1個可選的位置...

資料結構和演算法 字串 (二 字串排序 上)

不看 演算法4 都不知道字串排序也能講這麼多,之前還以為就是簡單的strcmp就完事了,不過看了發現沒這麼簡單,沒這麼簡單的話,就趕緊來學一學吧。之前是不打算寫這個的,直到我看到後面了之後,才發現需要寫乙個對比,才能更好的理解後面的字元排序法,所以就起了乙個0的序號。從排序說起,我們學過的排序有冒泡...

資料結構3 字串

string的基本操作函式要會,拷貝,查詢 hw筆試第一題,兩個字串,前面是全量字符集,後面是已占用字符集 用 隔開 輸出剩餘的字符集。1 include2 include3 using namespace std 4string stringoperate string str1,string s...