字符串模式匹配 - KMP算法(轉(zhuǎn))

字符串匹配是計算機的基本任務(wù)之一。

舉例來說屉来,有一個字符串"BBC ABCDAB ABCDABCDABDE"务傲,我想知道,里面是否包含另一個字符串"ABCDABD"夯到?

許多算法可以完成這個任務(wù)嚷缭,Knuth-Morris-Pratt算法(簡稱KMP)是最常用的之一。它以三個發(fā)明者命名黄娘,起頭的那個K就是著名科學(xué)家Donald Knuth峭状。

這種算法不太容易理解,網(wǎng)上有很多解釋逼争,但讀起來都很費勁优床。直到讀到Jake Boxer的文章,我才真正理解這種算法誓焦。下面胆敞,我用自己的語言,試圖寫一篇比較好懂的KMP算法解釋杂伟。

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

image

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

image

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

image

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

image

直到字符串有一個字符三圆,與搜索詞對應(yīng)的字符不相同為止。

image

這時避咆,最自然的反應(yīng)是舟肉,將搜索詞整個后移一位,再從頭逐個比較牌借。這樣做雖然可行度气,但是效率很差,因為你要把"搜索位置"移到已經(jīng)比較過的位置膨报,重比一遍。

image

一個基本事實是,當(dāng)空格與D不匹配時现柠,你其實知道前面六個字符是"ABCDAB"院领。KMP算法的想法是,設(shè)法利用這個已知信息够吩,不要把"搜索位置"移回已經(jīng)比較過的位置比然,繼續(xù)把它向后移,這樣就提高了效率周循。

image

怎么做到這一點呢强法?可以針對搜索詞,算出一張《部分匹配表》(Partial Match Table)湾笛。這張表是如何產(chǎn)生的饮怯,后面再介紹,這里只要會用就可以了嚎研。

image

已知空格與D不匹配時蓖墅,前面六個字符"ABCDAB"是匹配的。查表可知临扮,最后一個匹配字符B對應(yīng)的"部分匹配值"為2论矾,因此按照下面的公式算出向后移動的位數(shù):

移動位數(shù) = 已匹配的字符數(shù) - 對應(yīng)的部分匹配值

因為 6 - 2 等于4,所以將搜索詞向后移動4位杆勇。

image

因為空格與C不匹配贪壳,搜索詞還要繼續(xù)往后移。這時蚜退,已匹配的字符數(shù)為2("AB")闰靴,對應(yīng)的"部分匹配值"為0。所以关霸,移動位數(shù) = 2 - 0传黄,結(jié)果為 2,于是將搜索詞向后移2位队寇。

image

因為空格與A不匹配膘掰,繼續(xù)后移一位。

image

逐位比較佳遣,直到發(fā)現(xiàn)C與D不匹配识埋。于是,移動位數(shù) = 6 - 2零渐,繼續(xù)將搜索詞向后移動4位窒舟。

image

逐位比較,直到搜索詞的最后一位诵盼,發(fā)現(xiàn)完全匹配惠豺,于是搜索完成银还。如果還要繼續(xù)搜索(即找出全部匹配),移動位數(shù) = 7 - 0洁墙,再將搜索詞向后移動7位蛹疯,這里就不再重復(fù)了。

image

下面介紹《部分匹配表》是如何產(chǎn)生的热监。

首先捺弦,要了解兩個概念:"前綴"和"后綴"。 "前綴"指除了最后一個字符以外孝扛,一個字符串的全部頭部組合列吼;"后綴"指除了第一個字符以外,一個字符串的全部尾部組合苦始。

image

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

- "A"的前綴和后綴都為空集盈简,共有元素的長度為0凑耻;

- "AB"的前綴為[A],后綴為[B]柠贤,共有元素的長度為0香浩;

- "ABC"的前綴為[A, AB],后綴為[BC, C]臼勉,共有元素的長度0邻吭;

- "ABCD"的前綴為[A, AB, ABC],后綴為[BCD, CD, D]宴霸,共有元素的長度為0囱晴;

- "ABCDA"的前綴為[A, AB, ABC, ABCD],后綴為[BCDA, CDA, DA, A]瓢谢,共有元素為"A"畸写,長度為1;

- "ABCDAB"的前綴為[A, AB, ABC, ABCD, ABCDA]氓扛,后綴為[BCDAB, CDAB, DAB, AB, B]枯芬,共有元素為"AB",長度為2采郎;

- "ABCDABD"的前綴為[A, AB, ABC, ABCD, ABCDA, ABCDAB]千所,后綴為[BCDABD, CDABD, DABD, ABD, BD, D],共有元素的長度為0蒜埋。

image

"部分匹配"的實質(zhì)是淫痰,有時候,字符串頭部和尾部會有重復(fù)整份。比如待错,"ABCDAB"之中有兩個"AB"籽孙,那么它的"部分匹配值"就是2("AB"的長度)。搜索詞移動的時候朗鸠,第一個"AB"向后移動4位(字符串長度-部分匹配值)蚯撩,就可以來到第二個"AB"的位置础倍。

-- 阮一峰 - http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末烛占,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子沟启,更是在濱河造成了極大的恐慌忆家,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件德迹,死亡現(xiàn)場離奇詭異芽卿,居然都是意外死亡,警方通過查閱死者的電腦和手機胳搞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門卸例,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人肌毅,你說我怎么就攤上這事筷转。” “怎么了悬而?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵呜舒,是天一觀的道長。 經(jīng)常有香客問我笨奠,道長袭蝗,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任般婆,我火速辦了婚禮到腥,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蔚袍。我一直安慰自己乡范,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布页响。 她就那樣靜靜地躺著篓足,像睡著了一般。 火紅的嫁衣襯著肌膚如雪闰蚕。 梳的紋絲不亂的頭發(fā)上栈拖,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天,我揣著相機與錄音没陡,去河邊找鬼涩哟。 笑死索赏,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的贴彼。 我是一名探鬼主播潜腻,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼器仗!你這毒婦竟也來了融涣?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤精钮,失蹤者是張志新(化名)和其女友劉穎威鹿,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體轨香,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡忽你,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了臂容。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片科雳。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖脓杉,靈堂內(nèi)的尸體忽然破棺而出糟秘,到底是詐尸還是另有隱情,我是刑警寧澤丽已,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布蚌堵,位于F島的核電站,受9級特大地震影響沛婴,放射性物質(zhì)發(fā)生泄漏吼畏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一嘁灯、第九天 我趴在偏房一處隱蔽的房頂上張望泻蚊。 院中可真熱鬧,春花似錦丑婿、人聲如沸性雄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽秒旋。三九已至,卻和暖如春诀拭,著一層夾襖步出監(jiān)牢的瞬間迁筛,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工耕挨, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留细卧,地道東北人尉桩。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像贪庙,于是被迫代替她去往敵國和親蜘犁。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容