看了就明白,KMP算法亂彈~~

http://www.inf.fh-flensburg.de/lang/algorithmen/pattern/kmpen.htm

http://www.ics.uci.edu/~eppstein/161/960227.html



T爲主串ababaaababaaababaa,大小爲18;p爲模式串ababaa,大小爲6;

不免俗的我們先看下,普通的字符串匹配算法核心代碼:

    for (i=0; T[i] != '\0'; i++)
    {
         for (j=0; T[i+j] != '\0' && P[j] != '\0' && T[i+j]==P[j]; j++)
                ; //這有個分號喲。
             if (P[j] == '\0')
               {
                     report(i);//找到了一個匹配的
               }
    }


外循環主串索引i每次++,共18次,一路加到底。每次內循環模式串的索引j 變化範圍不定。最壞爲6次++運算。 算法的最壞情況18*6


KMP算法:

先看幾個概念:

前綴串:

prefix of x is a substring u with  u  =  x0 ... xb-1   where  b element {0, ..., k} i.e. x starts with u.

後綴串:

suffix of x is a substring u with u  =  xk-b ... xk-1   where  b element {0, ..., k} i.e. x ends with u.

真前綴串和真後綴串:

A prefix u of x or a suffix u of x is called a proper prefix or suffix, respectively, if unot equalx, i.e. if its length b is less than k.

邊界串:

border of x is a substring r with  r  =  x0 ... xb-1  and  r  =  xk-b ... xk-1   where  b element {0, ..., k-1} 

注意,邊界串的定義是必須同時滿足  真前綴串和真後綴串 的字符串才能被稱作 邊界串!!通俗點,邊界串就是兩頭相等的前後綴串的合體。

Borders r, s of a string x

r 和 s 都是邊界串!

邊界串擴展:

Let x be a string and a element A a symbol. A border r of x can be extended by a, if ra is a border of xa.

下圖中r邊界串被擴展成ra邊界串了。

Extension of a border

下面的代碼中:

數組b[]就是我們求出的模式串中每個元素的border值——就是邊界串的長度。

好吧,讓我們從頭說起,話說不知那一天高德納老爺爺,抱怨 普通字符串匹配算法效率太差了,就想改進他,怎麼改進他呢?

本質上就是減少普通字符串匹配算法中內外曾循環的次數,這就用到了邊界串了!

在下面的代碼中,我們看到外層循環索引還是++ 了18次。

改變的是內層的循環次數,至於怎麼減少的自己理解去吧!還用說就是用着個border值唄!border值就是網上的next值是也!

那,這個border值怎麼求的?請跳到下一段。

void kmpSearch()
{
    int i=0, j=0;//i爲主串索引,j爲模式串索引
    for ( ;i < 18; )//你瞧,和普通的字符串匹配算法多像呀:-)
    {
        for ( ; j>=0 && T[i]!=p[j]; ) 
          j=b[j];  //就是這裏了提高了效率
          i++; j++;
        if (j==m)
        {
            report(i-j);// 找到了,i-j 爲模式串在主串最初出現的位置。
            j=b[j];
        }
    }
}



KMP算的核心組件:預處理 算法

把下面這句看懂了,border 你就懂了。

The preprocessing algorithm comprises a loop with a variable j assuming these values. A border of width j can be extended by pi, ifpj = pi. If not, the next-widest border is examined by setting j = b[j]. The loop terminates at the latest if no border can be extended (j = -1).

Prefix of length i of the pattern with border of width b[i]

void kmpPreprocess() //求模式串中每個元素的border值。
{
    int i=0, j=-1;//i爲模式串的索引,j爲當前處理到第i個模式串中的元素的border值。
    b[i]=j; //b[] 是全局數組
    while (i<m)
    {
        while (j>=0 && p[i]!=p[j]) j=b[j]; //這句是核心請舉例畫圖,就可以明白配合上面的英文解釋。
        i++; j++;
        b[i]=j;
    }
}




















發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章