我也學演算法,學演算法

來源:互聯網
上載者:User

我也學演算法,學演算法

一直以來,對演算法都是理論大於實際,甚至沒有實際.

最近由於項目需要.從新瞭解了一下KMP演算法.唉,討厭這種被動的學習過程.

不過KMP演算法還是很有意思的,用了兩天的時間才總算是弄懂了.期間參考了網上的博文和資料結構.下面分享一下KMP演算法的心得.

KMP的總體思想是利用模式串本身的特性來最佳化匹配的步驟.如何利用自身的特性呢,KMP藉助一個數組來實現,也就是大多數教程中提到的next數組.後面我會介紹next數組是如何構建和使用的.

前面提到KMP演算法需要模式串滿足一定的條件,那麼這個條件是什麼呢.這裡直接引用資料結構書中的等式:

當k < j 時,  t1t2…tk-1tk = tj-(k-1)tj-k… tj-1 tj.

如果沒有這個等式,那麼KMP演算法無異於浪費了next大小的空間的最普通的字串匹配演算法.


下面用一張圖來描述一下這個等式在匹配子串的時候起到的作用:

(本圖片假定數組下標從1開始)首先我們找到等式: t1t2 = t6t7.所以當t8不匹配的時候,KMP演算法會自動對齊t1 t2 然後用t3和母串進行匹配.


那麼根據以上的分析,我們可以得出以下的幾個結論(可能得出的有點倉促,同學們還是需要結合課本來進行理解)

1. next數組和模式串的下標是一一對應的.

2. 每個字元對應的next儲存的是其前一個字元匹配的首碼的下標.從上面的圖中可以看到next[8]儲存的是3.

3. 第一個字母沒有首碼,所以它的next儲存的是一個無效的下標.在實際編程中,可以是-1

4. 如果一個字元的前面沒有滿足等式的子串,則其next儲存的是模式串的首字母的下標.


根據我們的結論,下面給出KMP演算法的實現:

void kmp_get_next(char *pattern, int next[]){    int i = 0, j = 0;    next[i] = -1;        while (i < strlen(pattern) - 1)    {        if (j == i || pattern[i] == pattern[j])        {            if (j != i)            {                j++;            }            i++;                        next[i] = j;        }        else if (j != 0)        {            j = next[j];        }        else        {            i++;        }    }}void kmp_print_next(char *pattern, int next[]){    int i = 0;     if (NULL == pattern)    {        return;    }    printf("%s 's next array is : \n", pattern);    for (i = 0; i < strlen(pattern); i++)    {        printf("%d\t", next[i]);    }}int kmp_is_match(char *pattern, char *basestr, int next[]){    int i = 0;     int j = 0;     while (i < strlen(basestr))    {        if (basestr[i] == basestr[j])        {            if (j == strlen(pattern))            {                return 0;            }            i++;            j++;        }        else        {            j = next[j];            if (j == -1)            {                i++;            }        }    }    return -1;}int kmp_get_match(char *pattern, char *basestr, int next[]){    int i = 0;     int j = 0;     while (i < strlen(basestr))    {        if (basestr[i] == basestr[j])        {            if (j == strlen(pattern))            {                return i;            }            i++;            j++;        }        else        {            j = next[j];            if (j == -1)            {                i++;            }        }    }    return -1;}

#include "kmp.h"int main(int argc, char **argv){    int ret = 0;    int i = 0;    char *pattern = "abaabc";    int next[10] = {0};    char *basestr = "abcabcabcabccacabdabaabcabceadb";    kmp_get_next(pattern, next);    printf("%s matched\n", kmp_is_match(pattern, basestr, next) == 0 ? "is" : "not");    ret = kmp_get_match(pattern, basestr, next);    return 0;}

KMP演算法其實理解起來並不難,比較難的就是構造next數組.至少對我而言是這樣.一旦數組構造出來,那剩下的就都好辦了.

可能是我理解的還不夠深把,寫之前覺得有很多內容可以分享,但是開始寫以後發現不知道該寫什麼.希望能夠對同學們有所啟發.




聯繫我們

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