KMP演算法的理解,虛擬碼,c代碼實現

來源:互聯網
上載者:User

標籤:

1、字串問題形式化定義:假設文本是一個長度為n的T[1..n],而模式是一個長度為m的數組P[1..m],其中m<=n,如果有T[s+1..s+m]==P[1..m],那麼就稱模式P在T中出現。s為有效位移,否則稱為無效位移。

2、方法:首先基於模式進行預先處理,然後找到所有有效位移(匹配)。

幾種方法的預先處理時間和匹配時間

演算法

預先處理時間

匹配時間

樸素演算法

0

o((n-m+1)*m)

有限自動機

o(m|所有有限長度字串的集合|)

o(n)

KMP

o(m)

o(n)

Rabin-karp

0(m)

o((n-m+1)*m)

3、樸素字串匹配演算法:通過迴圈的方式找到所有有效位移s。有效位移s的可能有n-m+1個,每次匹配需要m次,因此共需匹配(n-m+1)*m次。

虛擬碼:

NAIVE-STRING-MATCHER(T,P)

1. n=T.length

2. m=P.length

3. for s=0 to n-m

4.        if P[1..m] == T[s+1..s+m]

5.                 printf "Pattern occurs with shift" s

缺點:忽略了檢測無效s值時獲得的文本資訊。

4、Rabin-Karp演算法:初等數論的概念。暫且不研究。

5、利用有限自動機進行字串匹配:首先建立好一個有限自動機,然後根據有限自動機進行匹配。

有限自動機:包括五個元素,所有狀態的集合,初始狀態,接收狀態的集合,有限輸入字母表,轉移函數。

6、KMP演算法:通過首碼函數避免對無用位移進行檢測。也可以避免在自動機匹配中,對整個轉移函數的計算。主要原因在於字串中存在部分匹配的現象。

本質:針對待匹配的模式串的特點,判斷它是否有重複的字元,從而找到它的首碼與尾碼,進而求出相應的Next數組,最終根據Next數組而進行KMP匹配

next數組:記錄下字串P中的共有元素的位置,即第一個共有元素向後便宜多少可以到達第二個相同的元素哪兒。

"部分匹配"的實質是,有時候,字串頭部和尾部會有重複。比如,"ABCDAB"之中有兩個"AB",那麼它的"部分匹配值"就是2("AB"的長度)。搜尋字詞移動的時候,第一個"AB"向後移動4位(字串長度-部分匹配值),就可以來到第二個"AB"的位置。

大致思路:

kmp的比較函數:

1.首先初始化好NEXT數組, next[0]=0,next[1]=1

2.迴圈尋找模式P是否在T中

    1)首先比較P[i] == T[j],如果相等,繼續比較下一個,否則執行2.2)

    2)令j=next[j],繼續比較(這一步避免了回溯)

    3)如果j==0; 表明沒有匹配,則i++, j++

3.直到找到P在T中的位置或者T已經被比較晚結束。

當發生失配的情況下,j的新值next[j]取決於模式串中T[0 ~ j-1]中首碼和尾碼相等部分的長度, 並且next[j]恰好等於這個最大長度

next數組的初始化

1.定義next數組, 令next[0]=0, next[1]=1

2.從p[2]開始迴圈計算對應的next數組

3.    迴圈計算next[j]的值

4.        從next[j]往前找到某個p[i]=p[next[i]],如果相等則next[j]=next[i]+1

5.        否則,令i=next[i]繼續向前尋找,直到找到相等的為止。

6.        如果i=0,則表明模式P中沒有p[j]相同的首碼,令next[j]=1   

7、虛擬碼:

初始化NEXT數組

NEXT-FUNC(P, next)

1.let next[1..m] = -1

2.next[1]=0, next[2]=1

3.for i=3 to m

4.     j = i

5.     while j != 0

5.         if P[j] == P[next[j]]

6.               next[i]=next[j]+1

7.               break;

8.         else 

9.               j = next[j]

10.    if   j == 0 then next[j] = 1

KMP-CMP(T, P)    

1.NEXT-FUNC(P, next), j = 0; 

2.for T[i] form T[0] to T[n]

3.    if T[i] == S[j]  

4.        if j == m  then retrun true 

5.        then i++ j++

6.    else j = next[j];

7.    if j == 0 then i++ j++

#include <stdio.h>
int nextArr(char* p, int* next, int m){
    next[1] = 0;
    next[2] = 1;
    int i, j;
    for(i=3; i<m; i++){
        j=i;
        while(j!=0){
            if(p[j] == p[next[j]]){
                next[i] == next[j]+1;
                break;
            }else{
                j=next[j];
            }
        }
        if(j==0) {
            next[j] = 1;
        }
    }
    return 0;
}
int kmpCMP(char* t, char* p, int n, int m){
    int i = 0,j =0;
    int next[10];
    next[0] = 0;
    nextArr(p, next, m);
    for(i=0; i<m; i++){
        if(t[i]==p[j]){
            if(j==m-1){
                printf("%d\n", i-m+2);
                return 1;
            }else{
                j++;
                continue;
            }
        }else{
            j=next[j];
        }
        if(j==0){
        j=1;
        }
    }
    return 0;
}


KMP演算法的理解,虛擬碼,c代碼實現

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.