KMP(一) 模式匹配算法推導 --《部分匹配表》


概述:本文主要在理論層面上分析KMP的基本實現原理以及《部分匹配表》推導過程;不涉及代碼實現;如果您對KMP的實現代碼(OC)實現感興趣,可參考:
KMP(一) 模式匹配算法推導 --《部分匹配表》
KMP(二) 模式匹配算法實現
KMP(三) 字符串快速匹配示例


一: KMP主要解決的問題:

KMP是三位大牛:D.E.Knuth、J.H.Morris和V.R.Pratt同時發現的。其中第一位就是《計算機程序設計藝術》的作者!!

KMP算法要解決的問題就是在字符串(也叫主串,下文統一稱"P")中快速高效匹配子串(下文統一稱"S")并確定S在P中位置的問題。說簡單點就是我們平時常說的關鍵字(詞)搜索。

二. 字串樸素匹配算法實現:

看一個樸素匹配算法示例:
主串: P="BBC ABCDAB ABCDABCDABDE" 長度為Length_p
字串: S = "ABCDABD" 長度為Length_s



首先,字符串"BBC ABCDAB ABCDABCDABDE"的第一個字符與搜索詞"ABCDABD"的第一個字符,進行比較。因為B與A不匹配,所以搜索詞后移一位。



因為B與A不匹配,搜索詞再往后移。



就這樣,直到字符串有一個字符,與搜索詞的第一個字符相同為止。



接著比較字符串和搜索詞的下一個字符,還是相同。


直到字符串有一個字符,與搜索詞對應的字符不相同為止。


這時,最自然的反應是,將搜索詞整個后移一位,再從頭逐個比較。這樣做雖然可行,但是效率很差,因為你要把"搜索位置"移到已經比較過的位置,重比一遍,很明顯P的位置在回溯。分析樸素匹配算法時間復雜度為:
O((Length_p - Length_s + 1) * Length_s)

為方便后續說明,我們來約定一組表達規則:

主串 P 和字串 S 中有以下表達,示例如:
P[0] = "B"
P[4] = "A"
P[0~5]="BBC AB"
S[0] = "A"
S[2]="C"
S[1~3]="BCD"

我們觀察一下此時字串 S 和 主串P:
以下重要:
當S[0~5] = P[4~9] 并且 S[6] != P[10]時,S[0~3] 內沒有重復的字符,而切S[0~3] =P[4~7],所以在進行下一次比較時,我們可以直接將字串S移動至主串P的P[8] 位置開始比較,同時保持P的上一次查找位置不變(P[10]), 而不是像上圖一樣從P[5]開始循環比較,因為此時的P[5~8] 不可能與S(主要看S[0~3])匹配 ;這樣效率會大大提升;接下來看KMP是如何做的;

三. KMP算法示例分析:

KMP核心原則: 保持主串P上次查找位置(index_p)不回溯,移動字串S到合適的位置(index_s),下次比較起始位置分別為P[index_p]和S[index_s],不在比較P[0~index_p] 和 S[0~index_s],從而達到簡化匹配的計算過程;具體示例如下:

這里要引入一個《部分匹配表》概念;部分匹配表推導過程稍后做解釋;我們要做的先學會如何利用《部分匹配表》去實現KMP模式匹配,從而理解KMP的匹配過程;字串移位計算公式如下:

移動位數(S) = 已匹配的字符數 - 對應的部分匹配值

接著上述利用《部分匹配表》匹配分析:


7.

已知空格與D不匹配時,前面6個字符"ABCDAB"是匹配的。查表可知,最后一個匹配字符B對應的"部分匹配值"為2,照上面的公式算出向后移動的位數:
因為 6 - 2 等于4,所以將S向后移動4位。


8.

因為空格與C不匹配,搜索詞還要繼續往后移。這時,已匹配的字符數為2("AB"),對應B的"部分匹配值"為0。所以,移動位數 = 2 - 0,結果為 2,于是將搜索詞向后移2位。


9.

因為空格與A不匹配,而S已經到達最左端,故P繼續后移一位。


10.

逐位比較,直到發現C與D不匹配。于是,移動位數 = 6 - 2,繼續將搜索詞向后移動4位。


11.

逐位比較,直到搜索詞的最后一位,發現完全匹配,于是搜索完成。如果還要繼續搜索(即找出全部匹配),移動位數 = 7 - 0,再將搜索詞向后移動7位,這里就不再重復了。

四. 《部分匹配表》計算過程

首先,要了解兩個概念:"前綴"和"后綴"。 "前綴"指除了最后一個字符以外,一個字符串的全部頭部組合;"后綴"指除了第一個字符以外,一個字符串的全部尾部組合。注意:此處有個組合的概念,表達不同于KMP 算法實現中的前綴和后綴


"部分匹配值"就是"前綴"和"后綴"的最長的共有元素的長度。以"ABCDABD"為例,

1. "A"的前綴和后綴都為空集,共有元素的長度為0;
2. "AB"的前綴為[A],后綴為[B],共有元素的長度為0;
3. "ABC"的前綴為[A, AB],后綴為[BC, C],共有元素的長度0;
4. "ABCD"的前綴為[A, AB, ABC],后綴為[BCD, CD, D],共有元素的長度為0;
5. "ABCDA"的前綴為[A, AB, ABC, ABCD],后綴為[BCDA, CDA, DA, A],共有元素為"A",長度為1;
6. "ABCDAB"的前綴為[A, AB, ABC, ABCD, ABCDA],后綴為[BCDAB, CDAB, DAB, AB, B],共有元素為"AB",長度為2;
7. "ABCDABD"的前綴為[A, AB, ABC, ABCD, ABCDA, ABCDAB],后綴為[BCDABD, CDABD, DABD, ABD, BD, D],共有元素的長度為0。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,247評論 6 543
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,520評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,362評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,805評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,541評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,896評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,887評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,062評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,608評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,356評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,555評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,077評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,769評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,175評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,489評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,289評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,516評論 2 379

推薦閱讀更多精彩內容

  • 引言 字符串匹配一直是計算機科學領域研究和應用的熱門領域,算法的改進研究一直是一個十分困難的課題。作為字符串匹配中...
    潮汐行者閱讀 1,672評論 2 6
  • 數據結構 第8講 KMP算法 講這個算法之前,我們首先了解幾個概念: 串:又稱字符串,是由零個或多個字符組成的有限...
    rainchxy閱讀 1,336評論 0 3
  • KMP算法是一種改進的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt三人同時發現,...
    knowalker閱讀 1,336評論 2 9
  • 上午,起個大早,和剛露出頭的太陽一起,帶上大兒二兒直奔書畫班而去。看著周老師和已經有點功底的學生展出的字畫,大兒不...
    小鹿says閱讀 334評論 0 2
  • 我將那天的日期記在了本子上, 可是本子丟了; 我去了你家幻想著你還在, 可是那只是我的幻想; 你已經走了,而我還停...
    畢之先生閱讀 452評論 1 1