字串匹配:看毛片演算法及其它

來源:互聯網
上載者:User

很久就久仰過KMP演算法的大名,也學了不少時間,但是都是一知半解。最近重新拿起CLRS翻翻,發現基本能看懂了,順便把第32章:字串匹配給翻了一下。

樸素的字串匹配就不用多講了……

Rabin-Karp演算法的思想是產生數,把字元對應表為一個數字,然後一個子串就相當於一個整數,如果兩個整數值相等就是match成功了。當然,字元太多會溢出,那麼就用整數模一個素數的值來比較,但是又會存在碰撞。所以當找到一個命中點時,要用樸素的演算法來驗證。

有限狀態自動機有點複雜,看的半懂不懂的,但是總算知道有限自動機是什麼東西了。反正就是不斷接受變換狀態吧,網上還沒有找到詳細的實現代碼。我們這個縣級市的圖書館裡的電腦圖書大多是Window XP入門,Office辦公、Visual C++從入門到精通等很SB的書,但是竟然有這本如此NB的書。不過據說翻譯不好,而且除了對應研究方向的Ph.D和master,我想看的人不多吧。

最後就是KMP演算法了,得益於中國網民的輸入習慣,拼音IME打KMP出來的是看毛片……於是又稱看毛片演算法。

關於KMP,Matrix67處有很經典的教程。不過我最後理解還是根據CLRS,畢竟對著網頁和對著書學習的效果是不一樣的。

個人覺得精髓在於首碼函數next[q] = max{k: k<q && Pk是Pq的首碼}。

在匹配的過程中減少了判斷的冗(這個字讀rong 第三聲,打long找了好久……)餘,根據DD,看到CLRS上說KMP其實就是自動機實現的一種吧。

KMP厲害在時間、空間基本最優,而且兩個函數基本一樣,編程複雜度基本只比樸素的多幾行,而且也很好理解。

POJ3461是入門題,就是求子串出現的數目,裸的KMP。用C打了好久,開始是沒完全理解KMP,後來又是==達成=,s打成t之類的低級錯誤,還有就是C的數組下標從0開始,要改不少地方。

C代碼:

 

#include <stdio.h>#include <string.h>#define MAXN 19930317char s[MAXN],t[MAXN];int next[MAXN];int num,i,j,k,ans,lens,lent;void calc_next(){    j = -1;    next[0] = -1;    for (i = 1; i < lent; i++)    {        while ((j != -1) && (t[j+1] != t[i]))            j = next[j];        if (t[j+1] == t[i])            j++;        next[i] = j;    }}void KMP(){    j = -1;    for (i = 0; i < lens; i++)    {        while ((j != -1) && (t[j+1] != s[i]))            j = next[j];        if (s[i] == t[j+1])            j++;        if (j == lent - 1)        {            ans++;            j = next[j];        }    }}int main(){    scanf("%d", &num);    while (num--)    {        scanf("%s%s", t, s);        lent = strlen(t);        lens = strlen(s);        calc_next();        ans = 0;        KMP();        printf("%d\n", ans);    }    return 0;}

 

覺得還是PASCAL的好點,因為還不習慣C的數組從0開始的方式:

 

var  s,t:ansistring;  i,j,k,lens,lent,ans:longint;  num:longint;  next:array[0..19930317] of longint;procedure calc_next;begin  j:=0;  next[1]:=0;  for i:=2 to lent do  begin    while ((j>0)and(t[j+1]<>t[i])) do      j:=next[j];    if t[j+1]=t[i] then      j:=j+1;    next[i]:=j;  end;end;function kmp:longint;begin  j:=0;  kmp:=0;  for i:=1 to lens do  begin    while (j>0)and(t[j+1]<>s[i]) do      j:=next[j];    if t[j+1]=s[i] then      j:=j+1;    if j=lent then    begin      j:=next[j];      inc(kmp);    end;  end;end;begin  readln(num);  for k:=1 to num do  begin    readln(t);    readln(s);    lent:=length(t);    lens:=length(s);    calc_next;    writeln(kmp);  end;end.

聯繫我們

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