數(shù)據(jù)結(jié)構(gòu)與算法學(xué)習(xí)-KMP算法

題目: 有一個(gè)主串S = {a, b, c, a, c, a, b, d, c}, 模式串T 式串在主串中第一次出現(xiàn)的位置;
提示: 不需要考慮字符串大小寫問題, 字符均為小寫字母;
代碼實(shí)現(xiàn):
代碼準(zhǔn)備:

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 100 /* 存儲(chǔ)空間初始分配量 */

typedef int Status;        /* Status是函數(shù)的類型,其值是函數(shù)結(jié)果狀態(tài)代碼序芦,如OK等 */
typedef int ElemType;    /* ElemType類型根據(jù)實(shí)際情況而定臭杰,這里假設(shè)為int */
typedef char String[MAXSIZE+1]; /*  0號(hào)單元存放串的長(zhǎng)度 */

//----字符串相關(guān)操作---
/* 生成一個(gè)其值等于chars的串T */
Status StrAssign(String T,char *chars)
{
    int i;
    if(strlen(chars)>MAXSIZE)
        return ERROR;
    else
    {
        T[0]=strlen(chars);
        for(i=1;i<=T[0];i++)
            T[i]=*(chars+i-1);
        return OK;
    }
}

Status ClearString(String S)
{
    S[0]=0;/*  令串長(zhǎng)為零 */
    return OK;
}

/*  輸出字符串T。 */
void StrPrint(String T)
{
    int i;
    for(i=1;i<=T[0];i++)
        printf("%c",T[i]);
    printf("\n");
}

/* 返回串的元素個(gè)數(shù) */
int StrLength(String S)
{
    return S[0];
}

獲取next數(shù)組

void get_next(String T,int *next){
    int i,j;
    j = 1;
    i = 0;
    next[1] = 0;
    //abcdex
    //遍歷T模式串, 此時(shí)T[0]為模式串T的長(zhǎng)度;
    //printf("length = %d\n",T[0]);
    while (j < T[0]) {
        //printf("i = %d j = %d\n",i,j);
        if(i ==0 || T[i] == T[j]){
            //T[i] 表示后綴的單個(gè)字符;
            //T[j] 表示前綴的單個(gè)字符;
            ++i;
            ++j;
            next[j] = i;
            //printf("next[%d]=%d\n",j,next[j]);
        }else
        {
            //如果字符不相同,則i值回溯;
            i = next[i];
        }
    }
}

//輸出Next數(shù)組值
void NextPrint(int next[],int length)
{
    int i;
    for(i=1;i<=length;i++)
        printf("%d",next[i]);
    printf("\n");
}

匹配算法

int count = 0;
//KMP 匹配算法(1)
//返回子串T在主串S中第pos個(gè)字符之后的位置, 如不存在則返回0;
int Index_KMP(String S,String T,int pos){
    
    //i 是主串當(dāng)前位置的下標(biāo)準(zhǔn),j是模式串當(dāng)前位置的下標(biāo)準(zhǔn)
    int i = pos;
    int j = 1;
    
    //定義一個(gè)空的next數(shù)組;
    int next[MAXSIZE];
    
    //對(duì)T串進(jìn)行分析,得到next數(shù)組;
    get_next(T, next);
    count = 0;
    //注意: T[0] 和 S[0] 存儲(chǔ)的是字符串T與字符串S的長(zhǎng)度;
    //若i小于S長(zhǎng)度并且j小于T的長(zhǎng)度是循環(huán)繼續(xù);
    while (i <= S[0] && j <= T[0]) {
        
        //如果兩字母相等則繼續(xù),并且j++,i++
        if(j == 0 || S[i] == T[j]){
            i++;
            j++;
        }else{
            //如果不匹配時(shí),j回退到合適的位置,i值不變;
            j = next[j];
        }
    }
    
    if (j > T[0]) {
        return i-T[0];
    }else{
        return -1;
    }
    
}

對(duì)獲取next數(shù)組進(jìn)行優(yōu)化

void get_nextVal(String T,int *nextVal){
    int i,j;
    j = 1;
    i = 0;
    nextVal[1] = 0;
    while (j < T[0]) {
        if (i == 0 || T[i] == T[j]) {
            ++j;
            ++i;
            //如果當(dāng)前字符與前綴不同,則當(dāng)前的j為nextVal 在i的位置的值
            if(T[i] != T[j])
                nextVal[j] = i;
            else
            //如果當(dāng)前字符與前綴相同,則將前綴的nextVal 值賦值給nextVal 在i的位置
                nextVal[j] = nextVal[i];
        }else{
            i = nextVal[i];
        }
    }
}

優(yōu)化后匹配算法

int Index_KMP2(String S,String T,int pos){
    
    //i 是主串當(dāng)前位置的下標(biāo)準(zhǔn),j是模式串當(dāng)前位置的下標(biāo)準(zhǔn)
    int i = pos;
    int j = 1;
    
    //定義一個(gè)空的next數(shù)組;
    int next[MAXSIZE];
    
    //對(duì)T串進(jìn)行分析,得到next數(shù)組;
    get_nextVal(T, next);
    count = 0;
    //注意: T[0] 和 S[0] 存儲(chǔ)的是字符串T與字符串S的長(zhǎng)度;
    //若i小于S長(zhǎng)度并且j小于T的長(zhǎng)度是循環(huán)繼續(xù);
    while (i <= S[0] && j <= T[0]) {
        
        //如果兩字母相等則繼續(xù),并且j++,i++
        if(j == 0 || S[i] == T[j]){
            i++;
            j++;
        }else{
            //如果不匹配時(shí),j回退到合適的位置,i值不變;
            j = next[j];
        }
    }
    
    if (j > T[0]) {
        return i-T[0];
    }else{
        return -1;
    }
    
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末谚中,一起剝皮案震驚了整個(gè)濱河市渴杆,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌宪塔,老刑警劉巖磁奖,帶你破解...
    沈念sama閱讀 211,948評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異某筐,居然都是意外死亡比搭,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門南誊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來身诺,“玉大人,你說我怎么就攤上這事抄囚∶股模” “怎么了?”我有些...
    開封第一講書人閱讀 157,490評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵幔托,是天一觀的道長(zhǎng)穴亏。 經(jīng)常有香客問我,道長(zhǎng)柑司,這世上最難降的妖魔是什么迫肖? 我笑而不...
    開封第一講書人閱讀 56,521評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮攒驰,結(jié)果婚禮上蟆湖,老公的妹妹穿的比我還像新娘。我一直安慰自己玻粪,他們只是感情好隅津,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,627評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著劲室,像睡著了一般伦仍。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上很洋,一...
    開封第一講書人閱讀 49,842評(píng)論 1 290
  • 那天充蓝,我揣著相機(jī)與錄音,去河邊找鬼。 笑死谓苟,一個(gè)胖子當(dāng)著我的面吹牛官脓,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播涝焙,決...
    沈念sama閱讀 38,997評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼卑笨,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了仑撞?” 一聲冷哼從身側(cè)響起赤兴,我...
    開封第一講書人閱讀 37,741評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎隧哮,沒想到半個(gè)月后桶良,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,203評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡近迁,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,534評(píng)論 2 327
  • 正文 我和宋清朗相戀三年艺普,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鉴竭。...
    茶點(diǎn)故事閱讀 38,673評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡歧譬,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出搏存,到底是詐尸還是另有隱情瑰步,我是刑警寧澤,帶...
    沈念sama閱讀 34,339評(píng)論 4 330
  • 正文 年R本政府宣布璧眠,位于F島的核電站缩焦,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏责静。R本人自食惡果不足惜袁滥,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,955評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望灾螃。 院中可真熱鬧题翻,春花似錦、人聲如沸腰鬼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽熄赡。三九已至姜挺,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間彼硫,已是汗流浹背炊豪。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工凌箕, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人词渤。 一個(gè)月前我還...
    沈念sama閱讀 46,394評(píng)論 2 360
  • 正文 我出身青樓陌知,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親掖肋。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,562評(píng)論 2 349