字符串匹配 (KMP算法)

說(shuō)明
kmp的一些概述不做解釋了, 請(qǐng)參考: kmp算法 (百度百科)
參考了 阮一峰的: 字符串匹配的KMP算法
使用 C 語(yǔ)言實(shí)現(xiàn)的算法

部分匹配表
指在一串字符串中, 前綴與后綴中所共有的字符
前綴: 不包含字符串最后一個(gè)字符
后綴: 不包含字符串第一個(gè)字符

例如字符串 (AHABAD)
由此得出他們的部分匹配表為

A -> 0
前后都沒(méi)有所有共有字符數(shù)所以為 0

AH -> 0
前綴: A
后綴: H
它們沒(méi)有功能字符所有為 0

AHA -> 1
前綴: A, AH
后綴: A, HA
它們有共有的字符 共有數(shù)為 1

AHAB -> 0
前綴: A, AH, AHA
后綴: B, AB, HAB
它們沒(méi)有共有字符所有為 0

AHABA -> 1
前綴: A, AH, AHA, AHAB
后綴: A, BA, ABA, HABA
它們有共有字符 共有數(shù)為 1

由此得出 AHABAD 的前綴表為

0 1 2 3 4 5
A H A B A D
-1 0 0 1 0 1

部分匹配表算法實(shí)現(xiàn)過(guò)程 C 語(yǔ)言

int* prefix(char* s){
    /*
        接收一個(gè)字符串,
        返回一個(gè)部分匹配表  
    */

    int len = strlen(s),
        i = 0,
        j = -1, 

        *p = malloc(sizeof(int) * len);

    p[0] = -1;

    while(i < len - 1){
        if(j == -1 || s[i] == s[j]){
            p[++i] = ++j;
            continue;
        }
        j = p[j];
    }

    return p;
}

變量 i && j && p 的作用
在這里 p 可以看作是一次回溯,
應(yīng)為每當(dāng) if 條件不滿(mǎn)足時(shí) 則進(jìn)行一次回溯
那么此時(shí) j 的位置就需要重置到 p[j]

部分匹配表生成過(guò)程 以字符串 AHABAD 為例

變量 A H A B A D
s = AHABAD \ A A H A \
j = -1 -1, 0 0,-1, 0 0, 1 1, 0, -1, 0 0, 1 \
i = 0 0, 1 1, 2 2, 3 3, 4 4, 5 \
p[0]=-1 p[1]=0 p[2]= 0 p[3]=1 p[4]=0 p[5]=1 \

kmp

//kmp匹配算法
int kmpSearch(char *t, char *s){
    int t_len = strlen(t), 
        s_len = strlen(s);

    int *p = prefix(s), 
        m = 0, //代表母串匹配到的位置
        j = 0; // 代表字符匹配到的位置

    while(t_len > m && s_len > j){
        //j == -1 那么代表不和任何匹配直接向后移動(dòng)以為
        if(j == -1 ||  t[m] == s[j]){
            m++;
            j++;
            continue;
        }
        //當(dāng)不相等時(shí), 就去查詢(xún)部分匹配表
        j = p[j];
    }

    if (j == s_len)
        //返回匹配到的索引位置
        return m - j;
    return -1;
}

完整代碼
所需頭文件:
string.h stdlib.h

//部分匹配表算法
int* prefix(char* s){
    //prefix table
    int len = strlen(s),
        i = 0,
        j = -1, 
        *p = malloc(sizeof(int) * len);
    p[0] = -1;

    while(i < len - 1){
        if(j == -1 || s[i] == s[j]){
            p[++i] = ++j;
            continue;
        }
        j = p[j];   
    }

    return p;
}

//kmp
int kmpSearch(char *t, char *s){
    int t_len = strlen(t), 
        s_len = strlen(s);

    int *p = prefix(s), 
        m = 0,
        j = 0;

    while(t_len > m && s_len > j){
        if(j == -1 ||  t[m] == s[j]){
            m++;
            j++;
            continue;
        }
        j = p[j];
    }

    if (j == s_len)
        return m - j;
    return -1;

}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末使兔,一起剝皮案震驚了整個(gè)濱河市加缘,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖槐壳,帶你破解...
    沈念sama閱讀 221,635評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件莺葫,死亡現(xiàn)場(chǎng)離奇詭異垒棋,居然都是意外死亡褐捻,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)父腕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)弱匪,“玉大人,你說(shuō)我怎么就攤上這事璧亮∠艚耄” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,083評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵枝嘶,是天一觀(guān)的道長(zhǎng)帘饶。 經(jīng)常有香客問(wèn)我,道長(zhǎng)群扶,這世上最難降的妖魔是什么及刻? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,640評(píng)論 1 296
  • 正文 為了忘掉前任镀裤,我火速辦了婚禮,結(jié)果婚禮上缴饭,老公的妹妹穿的比我還像新娘暑劝。我一直安慰自己,他們只是感情好颗搂,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布担猛。 她就那樣靜靜地躺著,像睡著了一般丢氢。 火紅的嫁衣襯著肌膚如雪傅联。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,262評(píng)論 1 308
  • 那天疚察,我揣著相機(jī)與錄音蒸走,去河邊找鬼。 笑死稍浆,一個(gè)胖子當(dāng)著我的面吹牛载碌,可吹牛的內(nèi)容都是我干的猜嘱。 我是一名探鬼主播衅枫,決...
    沈念sama閱讀 40,833評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼朗伶!你這毒婦竟也來(lái)了弦撩?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,736評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤论皆,失蹤者是張志新(化名)和其女友劉穎益楼,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體点晴,經(jīng)...
    沈念sama閱讀 46,280評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡感凤,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了粒督。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片陪竿。...
    茶點(diǎn)故事閱讀 40,503評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖屠橄,靈堂內(nèi)的尸體忽然破棺而出族跛,到底是詐尸還是另有隱情,我是刑警寧澤锐墙,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布礁哄,位于F島的核電站,受9級(jí)特大地震影響溪北,放射性物質(zhì)發(fā)生泄漏桐绒。R本人自食惡果不足惜夺脾,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望茉继。 院中可真熱鬧劳翰,春花似錦、人聲如沸馒疹。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,340評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)颖变。三九已至生均,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間腥刹,已是汗流浹背马胧。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,460評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留衔峰,地道東北人佩脊。 一個(gè)月前我還...
    沈念sama閱讀 48,909評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像垫卤,于是被迫代替她去往敵國(guó)和親威彰。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評(píng)論 2 359