字串匹配基礎(上)

2021-10-01 14:23:14 字數 2568 閱讀 3388

單模式串匹配的演算法,也就是乙個串跟乙個串進行匹配;

多模式串匹配演算法,也就是在乙個串中同時查詢多個串;

bf 是 brute force 的縮寫,中文叫作暴力匹配演算法,也叫樸素匹配演算法。

需要懂以下兩個概念:

主串和模式串;

在字串 a 中查詢字串 b,那字串 a 就是主串,字串 b 就是模式串。我們把主串的長度記作 n,模式串的長度記作 m。因為我們是在主串中查詢模式串,所以 n>m。

bf演算法的思想:

在主串中,檢查起始位置分別是 0、1、2…n-m 且長度為 m 的 n-m+1 個子串,看有沒有跟模式串匹配的;

這種演算法最壞的情況時間複雜度為o(n*m);

雖然時間複雜度很高,但是在實際開發中,它卻是乙個比較常用的字串匹配演算法;原因如下:

第一,實際的軟體開發中,大部分情況下,模式串和主串的長度都不會太長。而且每次模式串與主串中的子串匹配的時候,當中途遇到不能匹配的字元的時候,就可以就停止了,不需要把 m 個字元都比對一下。所以,儘管理論上的最壞情況時間複雜度是 o(n*m),但是,統計意義上,大部分情況下,演算法執行效率要比這個高很多。

第二,樸素字串匹配演算法思想簡單,**實現也非常簡單。簡單意味著不容易出錯,如果有 bug 也容易暴露和修復。在工程中,在滿足效能要求的前提下,簡單是首選。

rk 演算法的全稱叫 rabin-karp 演算法,是由它的兩位發明者 rabin 和 karp 的名字來命名的。 bf 演算法的公升級版。

對樸素的字串匹配演算法稍加改造,引入雜湊演算法,時間複雜度立刻就會降低。

rk演算法思想:

過雜湊演算法對主串中的 n-m+1 個子串分別求雜湊值,然後逐個與模式串的雜湊值比較大小。如果某個子串的雜湊值與模式串相等,那就說明對應的子串和模式串匹配了。因為雜湊值是乙個數字,數字之間比較是否相等是非常快速的,所以模式串和子串比較的效率就提高了。

通過雜湊演算法計算子串的雜湊值的時候,需要遍歷子串中的每個字元。儘管模式串與子串比較的效率提高了,但是,演算法整體的效率並沒有提高。採取以下方式來進行雜湊演算法的設計:

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

比如要處理的字串只包含 a~z 這 26 個小寫字母,那我們就用二十六進製制來表示乙個字串。我們把 a~z 這 26 個字元對映到 0~25 這 26 個數字,a 就表示 0,b 就表示 1,以此類推,z 表示 25。

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

很容易就能得出這樣的規律:相鄰兩個子串 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)。

k 演算法整體的時間複雜度就是 o(n)。

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

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

在模式串匹配的基礎上去替換字串

def find chuan s1,s2,s3 length1 len s1 length2 len s2 s1 s1.replace s2,s3 lis return lis if name main print 輸入一行原串 s1 input print 原串s1的長度是 s,內容是 s len...

字串 堆分配基本操作

堆分配的儲存特點 1 依然是以一組位址連續的儲存單元存放串值字串行 2 儲存單元由動態分配 儲存結構typedef struct hstring 初始化 在這裡,使用for i 0,c chars c c i 這是乙個單獨的語句,沒有 塊。相當於for i 0,c chars c c i 但是在最開...

字串匹配問題 基礎棧

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