字串的模式匹配

2021-05-26 05:30:07 字數 2821 閱讀 5552

定義:

主串:"s1s2s3.............sn」 

模式串:   "p1p2p3................pm"

針對字串的模式匹配根本思想是在匹配過程中產生「失配」,模式串「向右滑動」的可行距離多遠的問題.換句話說也就是,當匹配過程中產生「失配」時,主串中等i個字元(i指標不回溯)應與模式串中哪個字元再比較?

假設此時應與模式中第k(k < j)個字元繼續比較,則模式中前k-1個字元的子串必須滿足下列關係式,且不可能存在k『 >k滿足下列關係式

"p1p2p3...p k-1" = "s i-k+1 s i-k+2......s i-1"            (1)

而已經得到的「部分匹配」的結果是

"p j-k+1 p j-k+2...p j-1 " =  "s i-k+1 s i-k+2......s i-1"  (2) 則

"p1p2p3...p k-1"  =   "p j-k+1 p j-k+2...p j-1 "            (3)

反之,若模式串中存在滿足(3)式的兩個子串,則當匹配過程中,主串中第i個字元與模式中第j個字元比較不等時,僅需將模式向右滑動至模式中第k個字元和主串中第i個字元對齊,此時,模式中有k-1個字元的子串  "p1p2p3...p k-1"必定與主串中第i個字元之前長度為k-1的子串 "s i-k+1 s i-k+2......s i-1"  相等,由此匹配僅需從模式中第k個字元與主串中第i個字元比較繼續進行。

若令next[j] = k,則next[j]表明當模式中第j個字元與主串中相應字元「失配」時,在模式中需重新和主串中該字元進行比較的字元的位置。由此可引出模式中的next函式的定義。

當 j =1時 next[j] = -1;

當 集合max不為空時,next[j]  =max

其它情況  next[j] = 0;

舉例說明按字元儲存形式得到的資料

j          1 2 3 4 5 6 7 8

模式串    a b a a b c a c

next[j]  -1 0 0 1 1 2 0 1

kmp演算法如下,       c#編寫的

static int index_kmp(string s, string t, int pos)

;int i = pos;

int j = 0;

while (i < s.length && j < t.length)

else

j = next[j];

}if (j >= t.length)

return i - t.length;

else

return 0;

//測試程式如下 

static void main(string args)

列印的索引為5。

kmp演算法的基礎是在已知模式串的next函式的基礎上執行的,下面介紹如何對模式串求出next[j]陣列。此函式值取決於模式串本身而和相匹配的主串無關,我們可從分析其定義出發遞推的方法求的next函式值。

由定義可知 next[0] = -1;

設next[j] =k,這表明在模式串中存在下列關係:

"p1p2p3...p k-1"  = "p j-k+1 p j-k+2...p j-1 " ,其中k 為滿足 1 < k < j的某個值,並且不可能存在k' > k 滿足等式 (3),此時next[j+1] = ? 可能情況有兩種

(1)若pk = pj,則表明在模式串中

"p1p2p3...p k"  = "p j-k+1 p j-k+2...p j"                                       (4)

並且不可能存在k' > k滿足等式(4),這就是說next[j+1] = k+1;  即next[j+1] = next[j] + 1;

(2)若pk != pj  ,則表明在模式串中

"p1p2p3...p k"  != "p j-k+1 p j-k+2...p j" ,

此時可把求next函式值的問題看成乙個模式匹配問題,整個模式串既是主串又是模式串,而當前在匹配的過程中,已有 p j-k+1 =p1, p j-k+2 = p2。。。p j-1 = p k-1 ,則當pk != pj        時應將模式向右滑動至以模式中的第next[k]個字元和主串中第j個字元比較。若next[k] = k'時,且 pj  = pk'       ,則說明在主串中第j+1個字元之前存在乙個長度為k'(即next[k])的最長子串,和模式串中從首字元起長度長度為k'的子串相等,即

"p1p2p3...p k』"  = "p j-k』+1 p j-k『+2...p j"  (1 < k' < k < j)            (5)

這就是說 next[j+1] = k' +1 ,即

next[j+1] = next[k] +1;

同樣的,若pj  != pk'     則將模式繼續向右滑動直至將模式中第next[k']個字串和pj    對齊......,依次類推,直至pj 和模式中某個字串匹配成功或者不存在k'(1 < k' < j) 滿足等式 (5),則

next[j +1] = 0;

根據以上思路,next函式**如下

static void get_next(string t, int next)

else}}

next函式的演算法複雜度在於模式串的長度,模式串的長度m比主串的長度能n要小的多,因此,對整個匹配演算法來說,所增加的這點時間是值得的。next函式針對有些情況尚有缺陷,比如模式串aaaab,則回溯時要遍歷4個a, 對此情況可直接跳到首位遍歷。可適當修改函式如下:

static void get_next(string t, int next)

else}}

字串模式匹配

include include include include include includeusing namespace std inline unsigned int64 getclock const char min a const int characters 26 int shiftta...

字串模式匹配

子串的定位操作通常稱作串的模式匹配,是各種串處理系統中最重要的操作之一。設有2 個串 主串 s和子串 t,串的簡單模式匹配演算法是 從主串 s 中的第乙個字元開始和子串 t中的第乙個字元比較,分別用i和 j 指示s串和 t串中正在比較的字元的位置。若相等,則繼續逐個比較後續字元 否則從主串 s的第二...

字串模式匹配

bf演算法 我們常用的暴力演算法,時間複雜度o n2 o n 2 演示 int bf const char text,const char pattern if flag return 1 return 0 kmp演算法 基於bf演算法的優化,他根據字串出現字首與字尾相同的情況進行優化 假設這裡sa...