定義:
主串:"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...