全網(wǎng)最通俗的KMP算法圖解

導(dǎo)語

本篇內(nèi)容研究字符串匹配問題,首先介紹字符串匹配問題诸蚕,引出Brute-Force算法及其優(yōu)化方法响疚,最后深入詳解KMP算法。文章結(jié)構(gòu)如下(全文閱讀需要30分鐘左右):

字符串匹配問題

1字符串匹配問題是什么

"字符串A是否為字符串B的子串?如果是的話出現(xiàn)在B的哪些位置?"該問題就是字符串匹配問題蹈丸,字符串A稱為模式串,字符串B稱為主串呐芥。

2應(yīng)用

字符串匹配應(yīng)用很廣泛逻杖,比如你想在一篇文章中找到某個關(guān)鍵字所在的位置,或者是你想在一份名單中找到某個名字是否出現(xiàn)等等

Brute-Force算法

1算法核心思想

Brute-Force算法簡稱BF算法(并不是Boy Friend),算法的核心思想跟名字一樣粗暴思瘟,如下所示:

2python代碼實現(xiàn)

假設(shè)n為主串長度荸百,m為模式串長度。

每一輪字符串比較:最差的情況為模式串最后一個字與主串不同其他都相同(如模式串為AAB滨攻,主串對應(yīng)部分為AAC)够话,必須走完整個字符串才能得出結(jié)果,因此復(fù)雜度為O(m)光绕。

所有輪字符串比較:最差的情況是移動到最后一次比較才尋找得到女嘲,總共需要n-m+1次,主串通常比模式串長很多诞帐,故Brute-Force時間復(fù)雜度為O(nm)

3算法優(yōu)化思路

最壞的情況:

兩個字符串是否相同的比較很難優(yōu)化欣尼,只能逐字比較。然而比較的趟數(shù)是可以減少的停蕉,因此盡可能減少比較的趟數(shù)是算法優(yōu)化的方向愕鼓,也是KMP算法的核心思想钙态。那么,讓我們開始KMP算法的講解拒啰。

KMP算法詳解

KMP算法于1977年被提出驯绎,全稱 Knuth–Morris–Pratt 算法,包含了三位前輩名字谋旦,分別是:Donald Knuth(K), James H. Morris(M), VaughanPratt(P)

1算法核心思想

如何減少匹配的趟數(shù)呢剩失?其實在每一次匹配過程中,我們就能夠判斷后續(xù)幾次匹配是否會成功册着,算法的核心就是每次匹配過程中推斷出后續(xù)完全不可能匹配成功的匹配過程拴孤,從而減少比較的趟數(shù),如圖所示:

因此甲捏,第一次匹配過之后演熟,就可以得出可以直接跳到第四趟再進行判斷的結(jié)論了。因為第一次匹配的時候司顿,前5個序列和主串相同芒粹,只需要對模式串進行分析,模式串出現(xiàn)了重復(fù)單元(即AB)大溜,在第一次匹配失敗后就可以直接跳躍到出現(xiàn)重復(fù)單元的位置化漆。

2next數(shù)組

next數(shù)組實質(zhì)上就是找出模式串中前后字符重復(fù)出現(xiàn)的個數(shù),為了能夠跳躍不可能匹配的步驟钦奋。

next數(shù)組的定義為:next[i]表示模式串A[0]至A[i]這個字串座云,使得前k個字符等于后k個字符的最大值,特別的k不能取i+i,因為字串一共才i+1個字符付材,自己跟自己相等毫無意義朦拖。

最終得到next數(shù)組為:

如何確定在移動過程中需要跳過多少步呢?下圖更直觀的體現(xiàn)了跳躍的過程:

對于上述紅色部分的計算跳過長度的公式為跳過的趟數(shù)=匹配上字符串中間字符長度-重復(fù)字符串長度

跳過這些步驟后并非再從頭開始匹配厌衔,而是從重復(fù)位置開始匹配

最終璧帝,我們不難得出如下結(jié)論:

3python代碼實現(xiàn)

1.首先建立KMP對象,初始化參數(shù):

2.建立next數(shù)組:

第一種最簡單的構(gòu)建方案富寿,時間復(fù)雜度為O(m平法)

第二種構(gòu)建方案睬隶,是一種遞推的方式進行構(gòu)建,時間復(fù)雜度為O(n+m):

考慮:如果next[0], next[1], ... next[x-1]均已知作喘,那么如何求出 next[x] 理疙?

我們已經(jīng)知道next[x-1],標(biāo)記next[x-1]=temp,則可以討論A[temp]和A[x]的值晕城,分2種情況討論:

第一種情況:A[temp]等于A[x]泞坦,也就是說在前一個next結(jié)果上又多了一個字符串相同的長度,因此next[x]為next[x-1]+1

第二種:當(dāng)A[temp]和A[x]不相等的時候砖顷,我們需要縮小temp,把temp變成next[temp-1]贰锁,直到A[temp]=A[x]為止赃梧。A[now]=A[x]時,就可以直接向右擴展了豌熄。

遞推構(gòu)建next數(shù)組代碼如下:

3.檢索過程代碼:

4.測試代碼:

作者原創(chuàng)授嘀,未經(jīng)授權(quán)請勿轉(zhuǎn)載

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市锣险,隨后出現(xiàn)的幾起案子蹄皱,更是在濱河造成了極大的恐慌,老刑警劉巖芯肤,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件巷折,死亡現(xiàn)場離奇詭異,居然都是意外死亡崖咨,警方通過查閱死者的電腦和手機锻拘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來击蹲,“玉大人署拟,你說我怎么就攤上這事「璨颍” “怎么了推穷?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長世曾。 經(jīng)常有香客問我缨恒,道長,這世上最難降的妖魔是什么轮听? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任骗露,我火速辦了婚禮,結(jié)果婚禮上血巍,老公的妹妹穿的比我還像新娘萧锉。我一直安慰自己,他們只是感情好述寡,可當(dāng)我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布柿隙。 她就那樣靜靜地躺著,像睡著了一般鲫凶。 火紅的嫁衣襯著肌膚如雪禀崖。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天螟炫,我揣著相機與錄音波附,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛掸屡,可吹牛的內(nèi)容都是我干的封寞。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼仅财,長吁一口氣:“原來是場噩夢啊……” “哼狈究!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起盏求,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤抖锥,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后碎罚,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體宁改,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年魂莫,在試婚紗的時候發(fā)現(xiàn)自己被綠了还蹲。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡耙考,死狀恐怖谜喊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情倦始,我是刑警寧澤斗遏,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站鞋邑,受9級特大地震影響诵次,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜枚碗,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一逾一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧肮雨,春花似錦遵堵、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至波丰,卻和暖如春壳坪,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背掰烟。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工爽蝴, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留扩灯,地道東北人。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓霜瘪,卻偏偏與公主長得像,于是被迫代替她去往敵國和親惧磺。 傳聞我的和親對象是個殘疾皇子颖对,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,916評論 2 344