KMP算法

問題:有一個文本串S,和一個模式串P,現(xiàn)在要查找P在S中的位置
輸入:“abcdef”,“bc”
"abcdefg" ,"ba"
輸出:1
-1

暴力匹配

并假設(shè)現(xiàn)在文本串S匹配到 i 位置,模式串P匹配到 j 位置,則有:
如果當(dāng)前字符匹配成功(即S[i] == P[j]),則i++,j++,繼續(xù)匹配下一個字符;
如果失配(即S[i]! = P[j]),令i = i - (j - 1),j = 0。相當(dāng)于每次匹配失敗時,i 回溯,j 被置為0。

int violent(char *s,char *p){
    int sLen = strlen(s);
    int pLen = strlen(p);
    int i = 0;
    int j = 0;
    while(i<sLen && j<pLen){
        if(s[i] == p[j]){
            i++;
            j++;
        }
        else{
            i = i-j+1;
            j = 0;
        }
    }
    //匹配成功,返回模式串p在文本串s中的位置,否則返回-1
    if (j == pLen)
        return i - j;
    else
        return -1;

}

KMP 算法
下面先直接給出KMP的算法流程(具體教程:<a href= http://blog.csdn.net/v_july_v/article/details/7041827> 詳細(xì)教程傳送門</a>):
假設(shè)現(xiàn)在文本串S匹配到 i 位置,模式串P匹配到 j 位置
如果j = -1,或者當(dāng)前字符匹配成功(即S[i] == P[j]),都令i++,j++,繼續(xù)匹配下一個字符;
如果j != -1,且當(dāng)前字符匹配失敗(即S[i] != P[j]),則令 i 不變,j = next[j]。此舉意味著失配時,模式串P相對于文本串S向右移動了j - next [j] 位。
換言之,當(dāng)匹配失敗時,模式串向右移動的位數(shù)為:失配字符所在位置 - 失配字符對應(yīng)的next 值,即移動的實際位數(shù)為:j - next[j],且此值大于等于1。(實際上相當(dāng)于當(dāng)前位和next[j]位比)

void GetNext(char* p,int next[])
{
    int pLen = strlen(p);
    next[0] = -1;
    int k = -1;
    int j = 0;
    while (j < pLen - 1)
    {
        //p[k]表示前綴,p[j]表示后綴
        if (k == -1 || p[j] == p[k])
        {
            ++k;
            ++j;
            if (p[j] != p[k])
                next[j] = k;   //之前只有這一行
            else
                //因為不能出現(xiàn)p[j] = p[ next[j ]],所以當(dāng)出現(xiàn)時需要繼續(xù)遞歸,k = next[k] = next[next[k]]
                next[j] = next[k];
        }
        else
        {
            k = next[k];
        }
    }
}
int kmp(char *s,char *p){
    int sLen = strlen(s);
    int pLen = strlen(p);
    int next[pLen];
    GetNext(p,next);
    int i = 0;
    int j = 0;
    
    while(i<sLen && j<pLen){
        if(j == -1 || s[i] == p[j]){
            i++;
            j++;
            
        }
        else{
            j = next[j];
        }
    }
    //匹配成功,返回模式串p在文本串s中的位置,否則返回-1
    if (j == pLen)
        return i - j;
    else
        return -1;
    
}

時間復(fù)雜度
我們發(fā)現(xiàn)如果某個字符匹配成功,模式串首字符的位置保持不動,僅僅是i++、j++;如果匹配失配,i 不變(即 i 不回溯),模式串會跳過匹配過的next [j]個字符。整個算法最壞的情況是,當(dāng)模式串首字符位于i - j的位置時才匹配成功,算法結(jié)束。 所以,如果文本串的長度為n,模式串的長度為m,那么匹配過程的時間復(fù)雜度為O(n),算上計算next的O(m)時間,KMP的整體時間復(fù)雜度為O(m + n)。

Reference:
<a >從頭到尾徹底理解KMP</a>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容