• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            那誰的技術(shù)博客

            感興趣領(lǐng)域:高性能服務(wù)器編程,存儲(chǔ),算法,Linux內(nèi)核
            隨筆 - 210, 文章 - 0, 評(píng)論 - 1183, 引用 - 0
            數(shù)據(jù)加載中……

            KMP算法的實(shí)現(xiàn)

            KMP算法是一種用于字符串匹配的算法,這個(gè)算法的高效之處在于當(dāng)在某個(gè)位置匹配不成功的時(shí)候可以根據(jù)之前的匹配結(jié)果從模式字符串的另一個(gè)位置開始,而不必從頭開始匹配字符串.
            因此這個(gè)算法的關(guān)鍵在于,當(dāng)某個(gè)位置的匹配不成功的時(shí)候,應(yīng)該從模式字符串的哪一個(gè)位置開始新的比較.假設(shè)這個(gè)值存放在一個(gè)next數(shù)組中,其中next數(shù)組中的元素滿足這個(gè)條件:next[j] = k,表示的是當(dāng)模式字符串中的第j + 1個(gè)(這里是遵守標(biāo)準(zhǔn)C語言中數(shù)組元素從0開始的約定,以下不再說明)發(fā)生匹配不成功的情況時(shí),應(yīng)該從模式字符串的第k + 1個(gè)字符開始新的匹配.如果已經(jīng)得到了模式字符串的next數(shù)組,那么KMP算法的實(shí)現(xiàn)如下:

            //?KMP字符串模式匹配算法
            //?輸入:?S是主串,T是模式串,pos是S中的起始位置
            //?輸出:?如果匹配成功返回起始位置,否則返回-1
            int?KMP(PString?S,?PString?T,?int?pos)
            {
            ????assert(NULL?
            !=?S);
            ????assert(NULL?
            !=?T);
            ????assert(pos?
            >=?0);
            ????assert(pos?
            <?S->length);
            ????
            ????
            if?(S->length?<?T->length)
            ????????
            return?-1;

            ????printf(
            "主串\t?=?%s\n",?S->str);
            ????printf(
            "模式串\t?=?%s\n",?T->str);

            ????
            int?*next?=?(int?*)malloc(T->length?*?sizeof(int));
            ????
            //?得到模式串的next數(shù)組
            ????GetNextArray(T,?next);

            ????
            int?i,?j;
            ????
            for?(i?=?pos,?j?=?0;?i?<?S->length?&&?j?<?T->length;?)
            ????
            {
            ????????
            //?i是主串游標(biāo),j是模式串游標(biāo)
            ????????if?(-1?==?j?||????????????????//?模式串游標(biāo)已經(jīng)回退到第一個(gè)位置
            ????????????S->str[i]?==?T->str[j])?//?當(dāng)前字符匹配成功
            ????????{
            ????????????
            //?滿足以上兩種情況時(shí)兩個(gè)游標(biāo)都要向前進(jìn)一步
            ????????????++i;
            ????????????
            ++j;
            ????????}

            ????????
            else????????????????????????//??匹配不成功,模式串游標(biāo)回退到當(dāng)前字符的next值
            ????????{
            ????????????j?
            =?next[j];
            ????????}

            ????}


            ????free(next);

            ????
            if?(j?>=?T->length)
            ????
            {
            ????????
            //?匹配成功
            ????????return?i?-?T->length;
            ????}

            ????
            else
            ????
            {
            ????????
            //?匹配不成功
            ????????return?-1;
            ????}

            }


            下面看看如何得到next數(shù)組.
            這是一個(gè)遞推求解的過程,初始的情況是next[0] = -1.
            假設(shè)在某一個(gè)時(shí)刻有如下的等式成立:str[0...k-1] = str[j - k...j - 1],那么next[j] = k,在這個(gè)前提下,繼續(xù)進(jìn)行下一個(gè)字符的匹配.
            1)如果str[0...k] = str[j - k...j],那么next[j + 1] = next[j] + 1 = k + 1.
            2)反之,如果上面的匹配不成立,那么就要從next[k]開始進(jìn)行新的匹配,如果成功的話,那么:
            next[j + 1] = next[next[j]] + 1 = next[k] + 1;
            如果還是不能匹配成功就再從next[next[k]]的位置開始進(jìn)行的新的匹配,直到匹配成功為止.如果這個(gè)過程一直進(jìn)行下去都沒有找到可以成功匹配的字符的話,那么next[j + 1] = 0,這時(shí)表示要從字符串的第一個(gè)位置開始新的匹配了.
            用一個(gè)公式表示上述的算法,那么可以寫作:
            next[j] =
            1)-1,當(dāng)j = 0時(shí);
            2) Max{k | 0 <= k < j && str[0..k - 1] = str[j - k...j - 1]};
            3)0,其他情況,此時(shí)匹配要從第一個(gè)位置重新開始.
            尋找next數(shù)組的算法如下:

            // ?得到字符串的next數(shù)組
            void ?GetNextArray(PString?pstr,? int ?next[])
            {
            ????assert(NULL?
            != ?pstr);?
            ????assert(NULL?
            != ?next);
            ????assert(pstr
            -> length? > ? 0 );

            ????
            // ?第一個(gè)字符的next值是-1,因?yàn)镃中的數(shù)組是從0開始的
            ????next[ 0 ]? = ? - 1 ;
            ????
            for ?( int ?i? = ? 0 ,?j? = ? - 1 ;?i? < ?pstr -> length? - ? 1 ;?)
            ????
            {
            ????????
            // ?i是主串的游標(biāo),j是模式串的游標(biāo)
            ????????
            // ?這里的主串和模式串都是同一個(gè)字符串
            ???????? if ?( - 1 ? == ?j? || ???????????????????????? // ?如果模式串游標(biāo)已經(jīng)回退到第一個(gè)字符
            ????????????pstr -> str[i]? == ?pstr -> str[j])???? // ?如果匹配成功
            ???????? {
            ????????????
            // ?兩個(gè)游標(biāo)都向前走一步
            ???????????? ++ i;
            ????????????
            ++ j;
            ????????????
            // ?存放當(dāng)前的next值為此時(shí)模式串的游標(biāo)值
            ????????????next[i]? = ?j;
            ????????}

            ????????
            else ???????????????????????????????? // ?匹配不成功j就回退到上一個(gè)next值
            ???????? {
            ????????????j?
            = ?next[j];
            ????????}

            ????}

            }



            完整的算法如下:
            /* *******************************************************************
            ????created:????2006/07/02
            ????filename:?????KMP.cpp
            ????author:????????李創(chuàng)
            ????????????????
            http://www.shnenglu.com/converse/
            ????????????????
            ????????????????參考資料:?嚴(yán)蔚敏<<數(shù)據(jù)結(jié)構(gòu)>>

            ????purpose:????KMP字符串匹配算法的演示
            ********************************************************************
            */


            #include?
            < stdio.h >
            #include?
            < stdlib.h >
            #include?
            < assert.h >
            #include?
            < string .h >

            #define ?MAX_LEN_OF_STR????30???????????? // ?字符串的最大長(zhǎng)度

            typedef?
            struct ?String???????????????? // ?這里需要的字符串?dāng)?shù)組,存放字符串及其長(zhǎng)度
            {
            ????
            char ????str[MAX_LEN_OF_STR];???? // ?字符數(shù)組
            ???? int ????????length;???????????????????? // ?字符串的實(shí)際長(zhǎng)度
            }
            String,? * PString;

            // ?得到字符串的next數(shù)組
            void ?GetNextArray(PString?pstr,? int ?next[])
            {
            ????assert(NULL?
            != ?pstr);?
            ????assert(NULL?
            != ?next);
            ????assert(pstr
            -> length? > ? 0 );

            ????
            // ?第一個(gè)字符的next值是-1,因?yàn)镃中的數(shù)組是從0開始的
            ????next[ 0 ]? = ? - 1 ;
            ????
            for ?( int ?i? = ? 0 ,?j? = ? - 1 ;?i? < ?pstr -> length? - ? 1 ;?)
            ????
            {
            ????????
            // ?i是主串的游標(biāo),j是模式串的游標(biāo)
            ????????
            // ?這里的主串和模式串都是同一個(gè)字符串
            ???????? if ?( - 1 ? == ?j? || ???????????????????????? // ?如果模式串游標(biāo)已經(jīng)回退到第一個(gè)字符
            ????????????pstr -> str[i]? == ?pstr -> str[j])???? // ?如果匹配成功
            ???????? {
            ????????????
            // ?兩個(gè)游標(biāo)都向前走一步
            ???????????? ++ i;
            ????????????
            ++ j;
            ????????????
            // ?存放當(dāng)前的next值為此時(shí)模式串的游標(biāo)值
            ????????????next[i]? = ?j;
            ????????}

            ????????
            else ???????????????????????????????? // ?匹配不成功j就回退到上一個(gè)next值
            ???????? {
            ????????????j?
            = ?next[j];
            ????????}

            ????}

            }


            // ?KMP字符串模式匹配算法
            // ?輸入:?S是主串,T是模式串,pos是S中的起始位置
            // ?輸出:?如果匹配成功返回起始位置,否則返回-1
            int ?KMP(PString?S,?PString?T,? int ?pos)
            {
            ????assert(NULL?
            != ?S);
            ????assert(NULL?
            != ?T);
            ????assert(pos?
            >= ? 0 );
            ????assert(pos?
            < ?S -> length);
            ????
            ????
            if ?(S -> length? < ?T -> length)
            ????????
            return ? - 1 ;

            ????printf(
            " 主串\t?=?%s\n " ,?S -> str);
            ????printf(
            " 模式串\t?=?%s\n " ,?T -> str);

            ????
            int ? * next? = ?( int ? * )malloc(T -> length? * ? sizeof ( int ));
            ????
            // ?得到模式串的next數(shù)組
            ????GetNextArray(T,?next);

            ????
            int ?i,?j;
            ????
            for ?(i? = ?pos,?j? = ? 0 ;?i? < ?S -> length? && ?j? < ?T -> length;?)
            ????
            {
            ????????
            // ?i是主串游標(biāo),j是模式串游標(biāo)
            ???????? if ?( - 1 ? == ?j? || ???????????????? // ?模式串游標(biāo)已經(jīng)回退到第一個(gè)位置
            ????????????S -> str[i]? == ?T -> str[j])? // ?當(dāng)前字符匹配成功
            ???????? {
            ????????????
            // ?滿足以上兩種情況時(shí)兩個(gè)游標(biāo)都要向前進(jìn)一步
            ???????????? ++ i;
            ????????????
            ++ j;
            ????????}

            ????????
            else ???????????????????????? // ??匹配不成功,模式串游標(biāo)回退到當(dāng)前字符的next值
            ???????? {
            ????????????j?
            = ?next[j];
            ????????}

            ????}


            ????free(next);

            ????
            if ?(j? >= ?T -> length)
            ????
            {
            ????????
            // ?匹配成功
            ???????? return ?i? - ?T -> length;
            ????}

            ????
            else
            ????
            {
            ????????
            // ?匹配不成功
            ???????? return ? - 1 ;
            ????}

            }

            posted on 2006-07-05 17:44 那誰 閱讀(7379) 評(píng)論(8)  編輯 收藏 引用 所屬分類: 算法與數(shù)據(jù)結(jié)構(gòu)

            評(píng)論

            # re: KMP算法的實(shí)現(xiàn)  回復(fù)  更多評(píng)論   

            數(shù)據(jù)結(jié)構(gòu)課程上給過的算法.
            說實(shí)話,我一直不能從書上那簡(jiǎn)單的描述中理解這個(gè)算法,直到現(xiàn)在仍然如此,慚愧.
            2006-07-05 18:13 | LOGOS

            # re: KMP算法的實(shí)現(xiàn)  回復(fù)  更多評(píng)論   

            沒關(guān)系,我也是花了好長(zhǎng)時(shí)間才整明白的,自己實(shí)現(xiàn)一下估計(jì)就能清楚好多了~~
            2006-07-05 18:18 | 創(chuàng)系

            # re: KMP算法的實(shí)現(xiàn)  回復(fù)  更多評(píng)論   

            求next函數(shù)其實(shí)就是自己和自己比一次。。kmp最重要就是求next函數(shù)了。。畫畫圖模擬一下,應(yīng)該比較容易理解的:)
            2006-07-08 12:18 |

            # re: KMP算法的實(shí)現(xiàn)  回復(fù)  更多評(píng)論   

            收藏
            2006-12-08 15:12 | todaygood

            # re: KMP算法的實(shí)現(xiàn)  回復(fù)  更多評(píng)論   

            2011-10-07 19:16 | kol

            # re: KMP算法的實(shí)現(xiàn)  回復(fù)  更多評(píng)論   

            這個(gè)應(yīng)該有簡(jiǎn)單的算法吧 ~~ 不用這么多的函數(shù) ~~
            2011-10-07 19:25 | kol

            # re: KMP算法的實(shí)現(xiàn)  回復(fù)  更多評(píng)論   

            算法貌似錯(cuò)了
            計(jì)算
            bacbabababacaca
            ababaca 的時(shí)候
            前綴是
            -1 0 -1 0 -1 3 -1
            結(jié)果 next[-1] 越界了
            2012-04-26 12:01 | Davis

            # re: KMP算法的實(shí)現(xiàn)  回復(fù)  更多評(píng)論   

            哦,不好意思,看錯(cuò)了
            2012-04-26 12:11 | Davis
            精品综合久久久久久88小说| 久久天天躁狠狠躁夜夜躁2O2O| 四虎国产精品免费久久久| 国产—久久香蕉国产线看观看| 国产精品gz久久久| 77777亚洲午夜久久多喷| 久久久久中文字幕| 97精品国产97久久久久久免费 | 乱亲女H秽乱长久久久| 国产福利电影一区二区三区久久老子无码午夜伦不 | 久久久久人妻一区精品性色av| 色综合久久中文综合网| 亚洲中文字幕久久精品无码喷水| 久久99精品国产麻豆宅宅| 国产成人无码精品久久久性色 | 色婷婷综合久久久久中文| 日产久久强奸免费的看| 久久青草国产精品一区| 国内精品伊人久久久久av一坑 | 国产伊人久久| 久久99热精品| 区亚洲欧美一级久久精品亚洲精品成人网久久久久 | 国产成人综合久久综合| 亚洲国产欧美国产综合久久 | 性欧美大战久久久久久久久 | 国产激情久久久久久熟女老人| 久久国产三级无码一区二区| 久久国产精品-国产精品| 色偷偷88888欧美精品久久久| 久久AV无码精品人妻糸列| 蜜桃麻豆www久久国产精品| 狠狠精品久久久无码中文字幕 | 99久久亚洲综合精品网站| 久久精品免费观看| 久久精品嫩草影院| 91久久香蕉国产熟女线看| 国产99久久久国产精品~~牛| 久久香蕉国产线看观看99| AAA级久久久精品无码区| 国产高潮国产高潮久久久91 | 久久综合噜噜激激的五月天|