演算法研究:字串的KMP模式比對

來源:互聯網
上載者:User

在樸素的模式比對演算法中,主串的pos值(i)是不斷地回溯來完成的(見字串的基本操作中的Index函數)。而電腦 的大仙們發現這種回溯其實可以是不需要的。既然i值不回溯,也就是不可以變小,那麼考慮的變化就是子串的pos值(j)了 。通過分析發現子串中如果有相等字元,j值的變化就會不相同,也就是說,這個j值的變化跟主串其實沒什麼關係,關鍵就 取決於子串的結構中是否有重複的問題。

我們把子串各個位置的j值變化定義為一個數組next,那麼next的長度就是 子串的長度(next[0]空置)。於是可以得到下面的函數定義。

範例程式碼:(改編自《大話資料結構》)

#include<iostream>using namespace std;    #define MAXSIZE 30typedef char String[MAXSIZE + 1]; //以'\0'結尾/* 產生一個串*/bool StrAssign(String Dest, char *ptr){    cout << "Assign Str ..." << endl;    int i;    for (i = 0; ptr[i] != '\0' && i < MAXSIZE; i++)        Dest[i] = ptr[i];    Dest[i] = '\0';    return true;}    int StrLength(String Src){    int i = 0;    while (Src[i] != '\0')        i++;    return i;}    void StrPrint(String Src){    cout << "Print Str ..." << endl;    for (int i = 0; Src[i] != '\0'; i++)        cout << Src[i];    cout << endl;    }/* 通過計算返回子串Sub的next數組。 */void GetNext(String Sub, int *next){    int i = 1;    int j = 0;    next[1] = 0;    while (i < StrLength(Sub))    {        if(j == 0 || Sub[i - 1] == Sub[j - 1])        {            ++i;            ++j;            next[i] = j;        }        else            j = next[j];/* 若字元不相同,則j值回溯 */    }}    void GetNextVal(String Sub, int *nextval){    int i = 1;    int j = 0;    nextval[1] = 0;    while (i < StrLength(Sub))    {        if(j == 0 || Sub[i - 1] == Sub[j - 1])        {            ++i;            ++j;            if (Sub[i - 1] != Sub[j - 1]) /* 若當前字元與前置詞字元不同 */                nextval[i] = j;/* 則當前的j為nextval在i位置的值 */            else                nextval[i] = nextval[j];/* 如果與前置詞字元相同,則將前置詞字元的 */            /* nextval值賦值給nextval在i位置的值 */        }        else            j = nextval[j];    }}/* 返回子串Sub在主串Src中第pos個字元之後的位置。若不存在,則函數傳回值為0。 */int IndexKMP(String Src, String Sub, int pos){    cout << "KMP Index ..." << endl;    int i = pos - 1;    int j = 0;    int next[10];    int len1 = StrLength(Src);    int len2 = StrLength(Sub);    /*GetNext(Sub, next);*/    GetNextVal(Sub, next);        while (i < len1 && j < len2)    {        /* 兩字母相等則繼續,與樸素演算法增加了j=0判斷 */        if (j == 0 || Src[i - 1] == Sub[j - 1])        {            ++i;            ++j;        }        else        {            j = next[j];/* j退回合適的位置,i值不變 */        }    }        if (j == len2)        return i - len2 + 1;    else        return 0;}    int main(void){    String Str1, Str2, Str3, Str4;    StrAssign(Str1, "defewabcabxwfew");    StrAssign(Str2, "abcabx");    StrAssign(Str3, "ababaaaba");    StrAssign(Str4, "htrhdhsgtrhababaaabafwrew");        int next[10]; //next[0]空置    GetNext(Str2, next);    cout << "Get Next array ..," << endl;    for (int i = 1; i < 7; i++)        cout << next[i];    cout << endl;        GetNext(Str3, next);    cout << "Get Next array ..," << endl;    for (int i = 1; i < 10; i++)        cout << next[i];    cout << endl;        GetNextVal(Str3, next);    cout << "Get NextVal array ..," << endl;    for (int i = 1; i < 10; i++)        cout << next[i];    cout << endl << endl;        cout << IndexKMP(Str1, Str2, 1) << endl;    cout << IndexKMP(Str4, Str3, 1) << endl;        return 0;}

輸出為:

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.