Horspool(字串匹配)演算法
阿新 • • 發佈:2019-01-27
Horsepool演算法是Boyer-Moore演算法的簡化版本,這也是一個空間換時間的典型例子。演算法把模式P和文字T的開頭字元對齊,從模式的最後一個字元開始比較,如果嘗試比較失敗了,它把模式向後移。每次嘗試過程中比較是從右到左的。
假設文字中,對齊模式最後一個字元的元素是c,Horspool演算法根據c的不同情況來確定移動距離,無論c是否和模式的最後一個字元相匹配。
一般來說,會存在下面四種情況。
情況1:看第一行,模式中不存在c(此時c就是字母A),模式的移動長度就是它的全部長度,移到第二行所示的位置。
情況2:看第二行,c(此時c就是字元O)正好是模式的最後一個字元,但是從右向左比較時,有字元不匹配,比如此時的A
情況3:看第一行,模式中存在c(此時c就是字元L),但是它不是模式的最後一個字元,移動時應該把模式中最右邊的c和文字中的c對齊,移到第二行所示的位置。
情況4:看第二行,c(此時c就是字元O)正好是模式的最後一個字元,但是從右向左比較時,有字元不匹配,比如此時的A和E不匹配。而此時模式中的其他m-1個字元包含c。移動的情況類似情況3,移動時應該把前m-1個字元中最右邊的c和文字中的c對齊,移到第三行所示的位置。
這說明,比起蠻力演算法每次總是移動一個位置,從右到左的字元比較使模式模式移動得更遠。然而,如果在每次嘗試時都必須檢查模式中的每個字元,它的優勢也會喪失殆盡。我們可以預先算出遇到某個字元要移動的距離,並把它存在一個表中。具體來說,對於每一個字元c,可以通過以下公式算出移動距離:
如對於模式BARBER,移動距離如下表所示:
字元c | A | B | E | R | 其它字元(包括空格,標點符號,下劃線和其它一些特殊字元) |
---|---|---|---|---|---|
移動距離t(c) | 4 | 2 | 1 | 3 | 6 |
c++實現
int Horspool(vector<char> & T,vector<char> & P)
{
int n = T.size();
int m = P.size();
vector <int> table(96,m);//以字母表中可列印字元為索引的陣列
for(int i = 0;i < m - 1;i++)
{
table[P[i] - 32] = m - 1 - i;//模式串中每個字元的移動距離,從左至右掃描模式,相同字元的最後一次改寫恰好是該字元在模式串的最右邊
}
int i = m - 1;
while(i <= n - 1)
{
int k = 0;
while(k <= m - 1 && P[m - 1 - k] == T[i - k])
k++;
if(k == m)
return i - m + 1;//匹配成功,返回索引
else
i += table[T[i] - 32];//模式串向右移動
}
return -1;//匹配失敗
}