1. 程式人生 > >對ZZL字串匹配演算法的改 ——ZZL最短匹配定理

對ZZL字串匹配演算法的改 ——ZZL最短匹配定理

對ZZL字串匹配演算法的改進

——ZZL最短匹配定理
張亮

     ZZL演算法是一種可做特殊用途的字串匹配演算法,本文將改進ZZL演算法,在ZZL演算法的基礎上,提出了ZZL最短匹配定理,根據模式串的自身特徵以進一步減少不必要的匹配次數。

字串匹配

     字串匹配的含義就是:在主串S中,從位置start開始查詢是否存在模式串(也稱作模式串)T,如在主串S中查詢到一個與模式串T相同的模式串,則模式串與主串匹配;如在主串S中未查詢到一個與模式串T相同的模式串,則不匹配。字串匹配用途廣泛,人們很早就對字串匹配演算法進行了研究,在BF(Brute Force)演算法的基礎上,提出了一些優秀的串匹配演算法,比如經典的KMP匹配演算法,BM演算法等。
     首先全文都有如下假設:
匹配的主串為S:S[1…N],長度為N;模式串為T:T[1…M],長度為M;N≥M;

ZZL匹配演算法

匹配思想

     現有的字串匹配演算法不論是按照模式串從左至右還是從右至左的順序匹配,都是直接進行比較,而ZZL演算法 的核心思想是:首先在主串S中查詢模式串T的首字母,每找到一個則將它的位置儲存,然後依次提取這些位置,從這些位置開始繼續匹配模式串T。對於頻繁使用 的要匹配的主串和模式串來說,由於預先儲存了模式串在主串中的所有儲存位置,所以匹配速度會非常快。

處理過程

     ZZL演算法也分為預處理和匹配兩個階段,預處理主要完成查詢模式串首字元在主串中的所有出現位置,並將其儲存在一個數組中;在預處理的基礎上,字串匹配演算法就可以從查詢到的模式串在主串中的位置開始,採用BF匹配模式串首字母之後的其餘部分。
時間按複雜度
     ZZL演算法的特點是簡單容易實現,如果不考慮演算法的預處理過程,若模式串首字母在主串中出現k次,則ZZL演算法最壞情況下比較次數為k*(M-1)<k*M。如果考慮演算法的預處理過程,則總的比較次數需再加上N次,即為k*M+N。
ZZL最短匹配定理
ZZL缺點分析
     觀察ZZL演算法,如果模式串首字母在主串中出現次數很多,那麼ZZL演算法記錄的匹配點將會增加,時間複雜度也隨之增加。讓我們先來考察下面的匹配場景:
S = tom

orrow, m any and m any m anufactories will close.
T = manufactories
     那麼ZZL演算法在預處理S時會找到4個開始匹配點,在上面的S串中用紅色 標明,然後從每個匹配點開始採用BF演算法嘗試匹配。然而事實上,只有在最後一個匹配點上T和S才匹配成功。前面的3個匹配點都不能使T和S匹配,如果能在預處理時就儘量排除這樣的點豈不是效率更高嗎?

ZZL最短匹配定理

     ZZL演算法並沒有利用模式串T的特徵,然而模式串T的特徵能夠幫助我們有效的減少匹配點。
     考察模式串T,我們發現T的首字元m僅出現了一次,而在S串中第二個m和第一個m的間隔小於T的長度,因此第一個m絕對不可能是正確的匹配點,可以直接排除。事實上,這是下面定理的一個特殊情況。
     首先定義模式串T的一個性質。
模式串T的最短ZZL匹配間距:


對任意模式串T,設T的首字元為c,c在T中出現的第二次位置為pos,如果c在T中僅出現一次,那麼令pos=M;
位置pos就是T的最短ZZL匹配間距,使用T.W來表示,易得T.W <= M;
ZZL最短匹配定理:

對任意主串S和模式串T,設T的首字元c在S中的連續出現位置為u和v,v >u。如果v – u < T.W,那麼在u位置S和T必定不匹配。
證明:
假設v – u < T.W,假設在u位置S和T匹配,那麼有
S[u] = T[0] = c;
S[u+1] = T[1];

S[u+M-1] = T[M-1];

由假設v – u < T.W
因此v必定位於區間(u, u+T.W)之中,並且T.W <= M,於是可得到
S[v] = T[i],0< i < T.W <= M ------ (1)
而v是T的首字元c在S中的出現位置,於是有
S[v] = c = T[0] ------ (2)
根據上面(1)和(2)兩式有T[i] = T[0], 0< i < T.W,這將違反T.W的定義。因此當v – u < T.W時,在u位置S和T必定不匹配。
證畢。

改進的ZZL演算法

     把ZZL最短匹配定理應用於ZZL演算法就得到了改進後的ZZ演算法,改進點是在ZZL的預處理階段,對匹配階段無影響。
     預處理階段分為兩部分,第一部分是求出T的ZZL最短匹配間距,第二階段是求出T在S中的匹配點。
     求T的ZZL最短匹配間距的虛擬碼如下所示:

c = T[0]
T.W = M
for i = 1 to M
begin
if T[i] == c then
    T.W = i
break;
        end if
    end
求T在S中的匹配點的虛擬碼如下所示:
j = 0;
for i = 0 to N - M
begin
      if S[i] == T[0] then // a potential match position
            if j == 0 || i – next[j-1] >= T.W then
                 next[j] = i;
                 j = j + 1;
            else
                 next[j-1] = i; // discard the previous one
            end if
      end if
end


     如果不考慮演算法的預處理過程,若模式串T首字母在主串S中出現k次,且滿足ZZL最短匹配間距,則ZZL演算法最壞情況下比較次數為k*(M-1)。如果考慮演算法的預處理過程,則總的比較次數為k*(M-1) + M + (N-M) = k*M + N。
因此對比ZZL演算法,改進後的ZZL演算法將能剔除那些T的首字母在S中不能滿足ZZL最短匹配間距的出現,從而減少比較次數和提高匹配速度。

結論

改進的ZZL演算法利用模式串T本身的特徵,通過ZZL最小匹配定理,能夠有效的減少ZZL的比較次數,提高匹配速度。
參考文獻
1.    朱戰立編著. 資料結構——使用C語言(第3版)[M]. 西安:西安交通大學出版社,2004
2.    紀福全 朱戰立. 一種可做特殊用途的字串匹配演算法 計算機與資訊科技[J] 200608