數(shù)據(jù)結(jié)構(gòu)和算法回顧-kmp

KMP字符串查找算法通過運用對這個詞在不匹配時本身就包含足夠的信息來確定下一個匹配將在哪里開始的發(fā)現(xiàn)瑟幕,從而避免重新檢查先前匹配的字符。

*此算法的核心是跳過肯定無法匹配的部分雳灾,達到高效匹配的目的播掷。 *

這里有一個可能很清晰介紹kmp的blog季二, 不過沒有代碼實現(xiàn),也沒有講原因舀寓。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/**
 * 字符串模式匹配 之 BF算法
 * Author : Yonggang Yuan
 */
#define EOS '\0' // End Of String
int main() {
    char text[] = "s a good肌蜻,Yonggang Yuan is a good student, is a good student twice ... is a good";
    char m[] = "s a good";
    int i, lenOfM = strlen(m);
    for( i=0; *(text+i) != EOS; i++ ) {
        if( memcmp(m, text+i, lenOfM) == 0 ) {
            printf("Match m at %d\n", i);
        }
    }

    return 0;
}
  • 前后綴
    一個字符串 ABCABKKJSCNABCAB
    前后綴為: 1)AB 2)ABCAB
    最大前后綴為: ABCAB
  • 跳過哪一部分
    移動位數(shù) = 已匹配的字符數(shù) - 對應的部分匹配值
    部分匹配值就是最大前后綴
    下面有兩個字符串
串a(chǎn) A B C A B K K J S C N A B C A B
i 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

|串b |A|B|C|A|B|D|F|
|---|-|-|-|-|-|-|-|-|
|j|0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|

在a[i=5],b[j=5]時候失配,按照kmp算法互墓,下一步就應該串b就應該向右移動(已匹配數(shù)-最大前后綴),用代碼表示就應該為i不變,j=next[j-1]蒋搜。
怎么理解j=next[j-1]?
next是字符串b的最大前后綴大小值組成的數(shù)組,比如子串b[0~5]的最大前后綴為AB,值也就為2,所以next[4]=2篡撵。而j=next[j-1]就表示j的下標變?yōu)閎[j]前面的字符串的最大前后綴,

上面這個例子可以用下圖表示

i 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
串a(chǎn) A B C A B K K J S C N A B C A B
串b A B C A B D F
j 0 1 2 3 4 5 6 7

從i[5],j[2]開始重新匹配,相對于暴力匹配法跳過i[12],由于i[34]與j[0~1]必然相等,也被忽略。

為什么i[1~2]可以直接跳過,會不會從i[1],j[0]開始直接匹配上了齿诞,那我來看看這情況酸休,如下圖

i 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
串a(chǎn) A B C A B K K J S C N A B C A B
串b A B C A B D F
j 0 1 2 3 4 5 6 7

因為在i[5],j[5]處失配,所以i[5]應該和什么匹配未知,已知的條件不能判斷祷杈,而用已知條件只要證明i[14]與j[03]絕對不匹配就行了斑司,
已知條件:
1)i[04]與j[04]已經(jīng)匹配上了
2)next數(shù)組(看做已知的,后面在詳細求解)
如果上圖的情況能匹配上,那么i[14]=j[03],又已知i[14]=j[14],所以j[03]=j[14]所以j[03]和j[14]是j[04]的前后綴,然而ABCAB的最大前后綴是AB值為2,已經(jīng)矛盾了但汞,所以i[14]與1[0~3]絕對不匹配宿刮,可以跳過。

  • next數(shù)組
    next[k]也就是字符串b[0~k]的最大前后綴私蕾,數(shù)組求法有點像數(shù)學歸納法僵缺,首先我們知道next[0]=0,然后遞歸求取next[1],next[2]...next[n]。
    一步步來看,先判斷b[1]和b[0]是不是相等踩叭,如果相等那b[0],b[1]就為b[0~1]的前后綴
  • golang代碼實現(xiàn)
func KmpMatch(astring string, bstring string) int {
        i, j := 1, 0
        next := make([]int, len(bstring))
        next[0] = 0
        for i < len(bstring) {
                if bstring[i] == bstring[j] {
                        next[i] = j + 1
                        i++
                        j++
                } else if j == 0 {
                        next[i] = 0
                        i++
                } else {
                        j = next[j]
                }
        }
        i, j = 0, 0
        for i < len(astring) {
                if astring[i] == bstring[j] {
                        if j == len(bstring)-1 {
                                return i
                        }
                        i++
                        j++
                } else {
                        if j > 0 {
                                j = next[j-1]
                        } else {
                                j = 0
                                i++
                        }
                }
        }
        return 0
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末磕潮,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子容贝,更是在濱河造成了極大的恐慌自脯,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件斤富,死亡現(xiàn)場離奇詭異膏潮,居然都是意外死亡,警方通過查閱死者的電腦和手機满力,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進店門焕参,熙熙樓的掌柜王于貴愁眉苦臉地迎上來轻纪,“玉大人,你說我怎么就攤上這事叠纷】讨悖” “怎么了?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵讲岁,是天一觀的道長我擂。 經(jīng)常有香客問我,道長缓艳,這世上最難降的妖魔是什么校摩? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮阶淘,結(jié)果婚禮上衙吩,老公的妹妹穿的比我還像新娘。我一直安慰自己溪窒,他們只是感情好坤塞,可當我...
    茶點故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著澈蚌,像睡著了一般摹芙。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上宛瞄,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天浮禾,我揣著相機與錄音,去河邊找鬼份汗。 笑死盈电,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的杯活。 我是一名探鬼主播匆帚,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼旁钧!你這毒婦竟也來了吸重?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤歪今,失蹤者是張志新(化名)和其女友劉穎晤锹,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體彤委,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年或衡,在試婚紗的時候發(fā)現(xiàn)自己被綠了焦影。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片车遂。...
    茶點故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖斯辰,靈堂內(nèi)的尸體忽然破棺而出舶担,到底是詐尸還是另有隱情,我是刑警寧澤彬呻,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布衣陶,位于F島的核電站,受9級特大地震影響闸氮,放射性物質(zhì)發(fā)生泄漏剪况。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一蒲跨、第九天 我趴在偏房一處隱蔽的房頂上張望译断。 院中可真熱鬧,春花似錦或悲、人聲如沸孙咪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽翎蹈。三九已至,卻和暖如春男公,著一層夾襖步出監(jiān)牢的瞬間荤堪,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工理澎, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留逞力,地道東北人。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓糠爬,卻偏偏與公主長得像寇荧,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子执隧,可洞房花燭夜當晚...
    茶點故事閱讀 42,925評論 2 344

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