Horspool是后綴搜索,也就是搜索已讀入文本中是否含有模式串的后綴;如果有,是多長,顯然,當后綴長度等於模式串的長度時,我們就找到了一個匹配。
Horspool算法認為:對於每個文本搜索窗口,將窗口內的最后一個字符(C)與模式串的最后一個字符進行比較。如果相等,則繼續從后向前驗證其他字符,直到完全相等或者某個字符不匹配。然后,無論匹配與否,都將根據在模式串的下一個出現位置將窗口向右移動。
匹配串:abcbcsdxzcxx
模式串:cbcac
這個時候我們從右向左進行對暗號,c-c,恩對上了,第二個b-a,不對啊,我們應該怎么辦?難道就這么放棄么。於是,模式串從不匹配的那個字符開始從右向左尋找匹配串中不匹配的字符b的位置,結果發現居然有,趕快對上趕快對上,別耽誤了。
匹配串:abcbcsdxzcxx
模式串: cbcac
然后繼續從最右邊的字符從右向左進行比較。這時候,我們發現了,d-c不匹配啊,而且模式穿里面沒有噢,沒辦法,只好移動一個模式串長度的單位了。
匹配串:abcbcsdxzcxx
模式串: cbcac
判斷模式串是否出現在源串的i位時,從i+m-1位開始比較,當比較到不同的時候。根據i+m-1位的內容對i作跳轉。
如果i+m-1位的字符不在模式串中出現,則i+=m,
(這是因為i+m-1不在模式串里出現,則從i,i+1,i+m-1開始的串,都不可能完全匹配。)
否則尋找該字符在模式串中最后一次出現的位置,
如果最后一次是出現在最后一位,
則找再上一次的出現,如果找不到,則i+=m,
i += m-最后一次出現的位置
(原因是,完全匹配的時候,至少i+m-1是匹配的,所以這個移動是找最后的一個位置,使得i+m-1位匹配)
真正編程的時候,不用寫這么多分支處理,直接在預處理的時候,用一個數組表示i每次要加上的數就行了。
1 int HorspoolMatch(byte* pSrc, int nSrcSize, byte* pSubSrc, int nSubSrcSize) 2 { 3 if (nSubSrcSize > nSrcSize) 4 { 5 return -1; 6 } 7 8 short skip[256]; 9 for(int i = 0; i < 256; i++) 10 { 11 skip[i] = nSubSrcSize; 12 } 13 for(int i = 0; i < nSubSrcSize - 1; i++) 14 { 15 skip[pSubSrc[i]] = nSubSrcSize - i - 1; 16 } 17 18 19 int pos = 0; 20 while(pos <= nSrcSize - nSubSrcSize) 21 { 22 int j = nSubSrcSize -1; 23 while(j >= 0 && pSrc[pos + j] == pSubSrc[j]) 24 { 25 j--; 26 } 27 if(j < 0 ) 28 { 29 break; 30 } 31 pos = pos + skip[pSrc[pos + nSubSrcSize -1]]; 32 } 33 return pos; 34 }