演算法 字串匹配之Z演算法

2022-07-05 06:27:10 字數 1293 閱讀 3331

求文字與單模式串匹配,通常會使用kmp演算法。後來接觸到了z演算法,感覺z演算法也相當精妙。在以前的博文中也有過用z演算法來解決字串匹配的題目。

下面介紹一下z演算法。

先一句話講清楚z演算法能求什麼東西。

輸入為乙個字串s,z演算法可以求出這個字串每乙個字尾與自身的最長公共字首lcp,z演算法可以求出乙個陣列z,z[i]表示suffix(i)與字串本身的最長公共字首。

接下來,介紹z演算法的具體內容。

記字串s的長度為n。

z演算法需要維護一對值,記為left和right,簡記為l和r。l和r滿足s[l,r]為s串的字首。當i為1的時候,暴力比較s[0,n-1]與s[1,n-1]可得此時的l與r,同時也得到了z[1],即suffix(1)與s本身的lcp。

假設計算至i-1,我們已經得到了當前的l與r,同時也得到了z[1]到z[i-1]的值,現在需要計算z[i]與新的l和r。

1.假設i>r,則說明不存在乙個結束於i或者i之後的串,同時這個串本身也為s的乙個字首,否則r不應該小於i。對於這種情況,需要重新計算新的l與r,令l=r=i,暴力比較s與suffix(i),得到z[i]=r-i+1=r-l+1。

2.此時i<=r,令k=i-l,可以斷言z[i]>=min(z[k],r-i+1)。因為根據l與r的含義,此時我們可以將l到r視作為字串的字首,那麼i相對於l的偏移量為k。

如果z[k]如果z[k]>=r-i+1,根據r的含義可知s[r+1]!=s[r-l+1],z[k]中大於r-i+1的匹配資訊因為s[r+1]!=s[r-l+1]而無效,但這並不意味著s[r+1]!=s[r-i+1],此時根據z[k]可以斷言z[i]至少是r-i+1,是否可以更大需要再進行計算,令l=i,更新r值,並得到此時的z[i]。

具體實現中,第二種情況的兩種子情況可以歸一化處理。

給出乙個c++實現**:

1

void z(char *s,int n=0

) 12

else22}

23}24 }

view code

過程中每個字元至多被l和r掃到一次,z演算法是線性的複雜度。

z演算法解決單模式串匹配的方法很簡單,令s為文字串,t為模式串,構造新串p=t+'#'+s,計算z陣列,從s在p中開始的位置向後掃瞄,如果z[i]=length(s),則說明此處有乙個匹配。當然其實也可以不加'#',那樣子的話判斷需要用》=而不是=。相較於kmp,對於解決單模式串匹配,如求所有匹配位置,其實用z演算法求的話是可以做到不用額外空間的(對於字串拼接,可以不用開乙個新的字串。過程中判斷匹配即可,不必儲存z陣列。),而kmp的話,不儲存模式串的next陣列,是沒辦法進行匹配運算的。

KMP字串匹配演算法 Z

最普通的字串匹配演算法就不記了,簡單貼一下 int strstr char sub,char str if q i 0 return p str return 1 下面說說我理解的kmp演算法,與普通匹配演算法不一樣的是,kmp演算法在子串匹配失效的時候,下一步並不是重新從子串的頭部開始匹配,而是根...

演算法之 字串匹配演算法

一說到兩個字串匹配,我們很自然就會想到用兩層迴圈來匹配,用這種方式就可以實現乙個字串是否包含另乙個字串了,這種演算法我們稱為 bf演算法。bf演算法,即暴力 brute force 演算法,是普通的模式匹配演算法,bf演算法的思想就是將目標串 s 的第乙個字元與模式串 t 的第乙個字元進行匹配,若相...

字串匹配演算法 字串匹配演算法總覽

字串匹配在文字處理裡非常重要,我們採用簡潔的python 把以下演算法一一實現並講解。樸素演算法 algorithm rabin karp 演算法 有限自動機演算法 finite automation knuth morris pratt 演算法 kmp algorithm boyer moore ...