程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> C說話kmp算法簡略示例和完成道理探討

C說話kmp算法簡略示例和完成道理探討

編輯:關於C++

C說話kmp算法簡略示例和完成道理探討。本站提示廣大學習愛好者:(C說話kmp算法簡略示例和完成道理探討)文章只能為提供參考,不一定能成為您想要的結果。以下是C說話kmp算法簡略示例和完成道理探討正文


之前看過kmp算法,其時接觸後總感到好深邃啊,抱著數據構造的數啃了一正午,終究才年夜致看懂,後來提起kmp也只剩下“奧,它是做形式婚配的”這點干貨。比來有空,翻出來算法導論看看,本來就是這麼簡略(下不說法式完成,思惟很簡略)。

形式婚配的經典運用:從一個字符串中找到形式字串的地位。如“abcdef”中“cde”湧現在原串第三個地位。從基本看起

樸實的形式婚配算法

A:abcdefg  B:cde

起首B從A的第一名開端比擬,B++==A++,假如全體成立,前往便可;假如不成立,跳出,從A的第二位開端比擬,以此類推。


/*
 *侯凱,2014-9-16
 *功效:形式婚配
 */
#include<iostream>
#include <string>
using namespace std;

int index(char *a,char *b)
{
    int tarindex = 0;
    while(a[tarindex]!='\0')
    {
        int tarlen = tarindex;
        int patlen;
        for(patlen=0;b[patlen]!='\0';patlen++)
        {
            if(a[tarlen++]!=b[patlen])
            {
                break;
            }
        }
        if(b[patlen]=='\0')
        {
            return tarindex;
        }
        tarindex++;
    }
    return -1;
}
int main()
{
    char *a = "abcdef";
    char *b = "cdf";
    cout<<index(a,b)<<endl;
      system("Pause");
}

思緒樸素無華,非常有用,然則時光龐雜度是O(mn),m、n分離是字符串和形式串的長度。形式婚配是一個罕見的運用成績,用的廣了,就有人設法主意去優化了。Rabin-Karp算法、無限主動機等等,前赴後繼,終究湧現了KMP(Knuth-Morris-Pratt)算法。

kmp算法

優化的處所:假如我們曉得形式中a和前面的是不相等的,那末第一次比擬後,發明前面的的4個字符均對應相等,可見a下次婚配的地位可以直接定位到f了。解釋主串對應地位i的回溯是不用要的。這是kmp最根本最症結的思惟和目的。

再好比:

因為abc 與前面的abc相等,可以直接獲得白色的部門。並且依據前一次比擬的成果,abc就不須要比擬了,如今只需從f-a處開端比擬便可。解釋主串對應地位i的回溯是不用要的。要變更的是形式串中j的地位(j紛歧定是從1開端的,好比第二個例子)

j的變更取決於形式串的前後綴的類似度,例2中abc和abc(接近x的),前綴為abc,j=4開端履行。

j是前一次履行的形式子串(前幾個,上例為6)中前綴的個數+1;它與形式字串中早年向後的前綴和從後向前的後綴的雷同子串是有關系的,由於下次這部門雷同的前綴就會挪動到這部門後綴的地位,由於假如挪動到後綴的後面地位,看圖:

所以假如此次是j,下次的地位應當就是j後面的子串的最年夜前綴的長度+1,用這個新的地位再和原字符串的i地位停止比擬就很幸福了。

此次是j,下次究竟是若干呢,這就觸及到怎樣盤算的成績了?其實只看形式串我們便可以構建出這個j->x的關系,關系稱為前綴函數,成果存儲在數組中,稱為前綴數組。

偽代碼:


compiter-prefix-function(P)
    m<-length[p]
    pi[1]<-0
    k<-0
    for q<-2 to m
        do while k>0 and P[k+1]!=P[q]
                    do k<-pi[k] //前綴的前綴...
           if P[k+1]==P[q]
                    then k<-k+1
           pi[q]<-k
    return pi

應用前綴數組可很快地完成形式婚配,法式婚配字符串中形式湧現的一切地位。


kmp-matcher(T, P)
    n<-length[T]
    m<-length[P]
    pi<-compiter-prefix-function(P)
    q<-0
    for i<-1 to n
        do while q>0 and P[q+1]!=T[i]
            do q<-pi[q] //前綴的前綴...
        if P[q+1]==T[i]
            then q<-q+1
        if q==m
            then print “Pattern occurs with shift”i-m
                    q<-pi[q]

這兩段代碼思惟完整雷同,假如和前綴分歧就比擬前綴的前綴…,比擬奇妙。假如kmp有難懂得的處所,估量就是這段偽碼的了。

KMP算法的時光龐雜度為O(n+m)。

這裡須要強調一下,KMP算法的僅當形式與主串之間存在許多部門婚配情形下能力表現它的優勢,部門婚配時KMP的i不須要回溯,不然和樸實形式婚配沒有甚麼差異。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved