[算法] KMP算法中如何計算next數(shù)組

1. 字符串匹配問題

假如我們有一個模式字符串ABCDABD和一個目標字符串BBC ABCDAB ABCDABCDABDE塌衰,
我們怎樣找到模式串在目標串中的匹配位置呢刨摩?

最容易想到的辦法是逐個比對源碼


2. KMP算法背景

KMP算法是一種改進的字符串匹配算法铐望,
由D.E.Knuth扶平,J.H.Morris和V.R.Pratt同時發(fā)現(xiàn)清女,因此人們稱它為KMP算法玩徊。
KMP算法的關鍵是利用匹配失敗后的信息的榛,
盡量減少模式串與目標串的重復匹配次數(shù)以達到快速匹配的目的琼了。
具體實現(xiàn)是利用一個事先計算好的next數(shù)組,
其中包含了模式串的前綴與后綴特征夫晌。


3. 往后跳多遠

我們觀察一下雕薪,看看逐個比對會包含哪些重復計算,然后想辦法消除它晓淀。
考慮某個中間步驟所袁,

BBC ABCDAB ABCDABCDABDE
    ABCDABD

模式串ABCDABD的子串ABCDAB都比對成功了,可是凶掰,在D處失敗了燥爷。
于是下一步,我們會向后移動一個字符懦窘,繼續(xù)比對,

BBC ABCDAB ABCDABCDABDE
     ABCDABD

可是畅涂,我們可以移動的更遠一些嗎港华?
能不能把目標串中的ABCDAB全都跳過?

BBC ABCDAB ABCDABCDABDE
          ABCDABD

好像不行午衰,跳的太遠了立宜,我們得從這里開始冒萄,

BBC ABCDAB ABCDABCDABDE
        ABCDABD

因為ABCDAB前綴和后綴包含重疊的部分。


我們稱ABABCDAB前綴和后綴的最長公共序列橙数。

跳多遠=ABCDAB長度 - 前綴和后綴的最長公共序列長度


4. next數(shù)組

前綴和后綴的最長公共序列尊流,只和模式串有關,是模式串本身的特征灯帮。
所以奠旺,我們就可以事先算好模式串前n個字符的前綴和后綴的最長公共序列的長度
把它們存起來施流,稱為next數(shù)組

對于模式串agctagcagctagct來說鄙信,
它的next數(shù)組為[0,0,0,0,1,2,3,1,2,3,4,5,6,7,4]瞪醋,
即,模式串的前i+1個字符的前綴和后綴的最長公共序列的長度為next[i]装诡。

例如:agctagcagctagct的前6個字符agctag的前綴和后綴的最長公共序列的長度為next[5]=2银受。

怎樣計算這個數(shù)組呢?
我們可以利用next[0]~next[i]來計算next[i+1]鸦采。
假設pattern='agctagcagctagct'

a:next[0]=0宾巍,
ag:pattern[1]=g,pattern[0]=a渔伯,不相等顶霞,所以next[1]=0,
agc:pattern[2]=c锣吼,pattern[0]=a选浑,不相等,所以next[2]=0玄叠,
agct:pattern[3]=t古徒,pattern[0]=a,不相等读恃,所以next[3]=0隧膘,
agcta:pattern[4]=a,pattern[0]=a寺惫,相等疹吃,所以next[4]=1,
agctag:pattern[5]=g肌蜻,pattern[1]=g互墓,相等,所以next[5]=2蒋搜,
agctagc:pattern[6]=c篡撵,pattern[2]=c判莉,相等,所以next[6]=3育谬,
……
agctagcagctagc:pattern[13]=c券盅,pattern[6]=c,相等膛檀,所以next[13]=7

5. 次長公共序列

難點來了锰镀。
agctagcagctagct:pattern[14]=t,pattern[7]=a咖刃,不相等泳炉。
怎么辦?于是next[14]=0嗎嚎杨?

很顯然不行花鹅,因為agct是前綴和后綴的最長共同序列,next[14]=4枫浙。

尋找agct基于以下考慮刨肃,
如圖,橙色的A表示已經確定的最長公共序列箩帚,綠色的T將要與開頭的A后面的元素進行比較真友。
如果比對失敗,我們需要尋找次長公共序列B紧帕,然后T再與開頭的B后面元素進行比對盔然。

我們看到,三幅圖中焕参,橙色塊都是相等的轻纪,
如果存在次長公共序列,第二幅圖表明叠纷,橙色塊必然同時以B開頭且以B結尾刻帚。
即,如第三幅圖所示涩嚣,
這表明崇众,T位置的次長公共序列長度,就是橙色塊的最長公共序列長度航厚。

因此顷歌,計算agctagcagctagc的次長公共序列,就要計算B=agctagc的最長公共序列幔睬,
而這個已經計算過了眯漩,next[6]=3,得到agc
然后與agc后面的元素t進行比對赦抖,相等舱卡,next[14]=4。


參考:
Github:kmp源碼
視頻:求kmp的next數(shù)組
從頭到尾徹底理解KMP(2014年8月22日版)
字符串匹配的KMP算法- 阮一峰的網絡日志

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末队萤,一起剝皮案震驚了整個濱河市轮锥,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌要尔,老刑警劉巖舍杜,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異赵辕,居然都是意外死亡既绩,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進店門还惠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來熬词,“玉大人,你說我怎么就攤上這事吸重。” “怎么了歪今?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵嚎幸,是天一觀的道長。 經常有香客問我寄猩,道長嫉晶,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任田篇,我火速辦了婚禮替废,結果婚禮上,老公的妹妹穿的比我還像新娘泊柬。我一直安慰自己椎镣,他們只是感情好,可當我...
    茶點故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布兽赁。 她就那樣靜靜地躺著状答,像睡著了一般。 火紅的嫁衣襯著肌膚如雪刀崖。 梳的紋絲不亂的頭發(fā)上惊科,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天,我揣著相機與錄音亮钦,去河邊找鬼馆截。 笑死,一個胖子當著我的面吹牛蜂莉,可吹牛的內容都是我干的蜡娶。 我是一名探鬼主播混卵,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼翎蹈!你這毒婦竟也來了淮菠?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤荤堪,失蹤者是張志新(化名)和其女友劉穎合陵,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體澄阳,經...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡拥知,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了碎赢。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片低剔。...
    茶點故事閱讀 39,932評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖肮塞,靈堂內的尸體忽然破棺而出襟齿,到底是詐尸還是另有隱情,我是刑警寧澤枕赵,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布猜欺,位于F島的核電站,受9級特大地震影響拷窜,放射性物質發(fā)生泄漏开皿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一篮昧、第九天 我趴在偏房一處隱蔽的房頂上張望赋荆。 院中可真熱鬧,春花似錦懊昨、人聲如沸窄潭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽狈孔。三九已至,卻和暖如春材义,著一層夾襖步出監(jiān)牢的瞬間均抽,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工其掂, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留油挥,地道東北人。 一個月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像深寥,于是被迫代替她去往敵國和親攘乒。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,884評論 2 354

推薦閱讀更多精彩內容