KMP字符串匹配算法

1. KMP算法用途算法

KMP算法用於解決主字符串和模式字符串匹配的問題。若是完成匹配,返回模式字符串在主字符串匹配的初始索引。若是不匹配,返回-1。數組

2. PMT(Partial Match Table):部分匹配表(模式字符串)spa

部分匹配表是KMP算法的核心,定義:前綴集合和後綴集合交集中最長元素的長度。3d

前綴集合:若是字符串M = A + S,A和S非空,則A是M的一個前綴,全部的前綴組成前綴集合。code

後綴集合:若是字符串M = A + S,A和S非空,則S是M的一個後綴,全部的後綴組成後綴集合。blog

圖中表示了Index = 10時,PMT = 4的計算過程,前綴字符串abab與後綴字符串abab匹配。索引

3. KMP算法實現字符串

若是主字符串是T,匹配字符串是P,T[ i ] != P[ j ]時,此時能夠經過右移匹配字符串PMT[ j - 1 ]個單位來解決,即令 j = PMT[ j - 1]get

若是T[ i ] = P[ j ],則i++, j++,表示目前匹配class

若是T[ i ] != P[ j ]

  若是 j == -1,則須要 i++, j++,j++ 表示P 從0開始匹配,i++表示當前不匹配,從下一個位置開始匹配。

  若是 j != -1,則從後綴字符串與前綴字符串已經匹配,令 j = next[j]便可。

循環結束,當 j == strlen(p)時,表示徹底匹配,此時返回 i - j 表示匹配的起始位置。

例:主字符串:"abababcab",子字符串:"ababc"

匹配過程:

 

爲了簡化計算,引入next數組記錄 j 索引處 PMT[ j - 1 ]的數值。

代碼實現

int KMP(char * t, char * p) 
{
    int i = 0; 
    int j = 0;

    while (i < strlen(t) && j < strlen(p))
    {
        if (j == -1 || t[i] == p[j]) 
        {
            i++;
                   j++;
        }
         else 
                   j = next[j];
        }

    if (j == strlen(p))
       return i - j;
    else 
       return -1;
}

4. PMT, next實現過程

經過移動與自身字符串匹配求next:

注意:若是不匹配,j 的值應該設爲:next[j],繼續向下匹配,直到爲 j = -1 爲止再從0開始匹配,下圖說明了緣由。

 

代碼實現:

void getNext(char * p, int * next)
{
    next[0] = -1;
    int i = 0, j = -1;

    while (i < strlen(p))
    {
        if (j == -1 || p[i] == p[j])
        {
            ++i;
            ++j;
            next[i] = j;
        }    
        else
            j = next[j];
    }
}
相關文章
相關標籤/搜索