Horspool算法是一種基於后綴的匹配方法,它的主要難點在於如何安全地移動窗口,以避免遺漏可能的成功匹配。
1,Horspool的基本思想
horspool算法將主串中匹配窗口的最后一個字符跟模式串中的最后一個字符比較。如果相等,繼續從后向前對主串和模式串進行比較,直到完全相等或者在某個字符處不匹配為止(如下圖中的α與σ失配) 。如果不匹配,則根據主串匹配窗口中的最后一個字符β在模式串中的下一個出現位置將窗口向右移動。
2,Horspool的求解過程
此處選擇參考文獻[1]中的一個例子來詳細介紹下Horspool的求解過程
在序列AGATACGATATATAC中搜索字符串ATATA。
首先,要構造失配時模式串中元素的移動距離數組d:
然后開始逐次匹配:
1)A G A T A C G A T A T A T A C
A T A T A
在主串的G處失配,此時模式串向右移動的距離是d[A]=2
2)A G A T A C G A T A T A T A C
A T A T A
又在主串G處失配,此時模式串向右移動的距離是d[G]=5
3)A G A T A C G A T A T A T A C
A T A T A
此處發現了一個匹配,我們可以繼續往下找,此時模式串向右移動的距離是d[A]=2
4)A G A T A C G A T A T A T A C
A T A T A
呃。。。又發現了一個匹配,再繼續往下找吧,此時模式串向右移動的距離依然是d[A]=2
5)A G A T A C G A T A T A T A C
A T A T A
移動后,主串指針pos>n-m了,搜索過程結束。
3,Horspool算法實現
這里我提供了一個第2小節中提到的DNA子串查找的horspool算法實現。
1 /*
2 * implementation of Horspool 3 * Author:Horspool 4 * Coder: Cobbliu 5 */
6 #define WORD 26
7 int horspool(char *T, int lenT, char *P, int lenP) 8 { 9 int d[WORD]; 10 int i, pos, j; 11
12 for(i = 0; i != WORD; i++) 13 d[i] = lenP; 14 for(i = 0; i != (lenP-1); i++) 15 d[P[i]-'A'] = lenP-i-1; 16
17 pos = 0; 18 while(pos < (lenT-lenP)){ 19 j = lenP-1; 20 while(j >= 0 && T[pos+j]==P[j]) //matching
21 j--; 22 if(j == -1) 23 return pos; 24 else //not matched
25 pos += d[T[pos+lenP-1]-'A']; 26 } 27
28 return -1; 29 }
4,Horspool算法復雜度
假設主串的長度為n,模式串的長度為m,那么Horspool算法最壞情況下的時間復雜度是O(mn),但平均情況下它的時間復雜度是O(n)。
5,參考文獻
[1] 《Flexible Pattern Matching in Strings》 Gonzalo Navarro & Mathieu Raffinot