(二)Boyer-Moore字符串查找算法

這是一種類似於KMP但是更高效一點、也更簡單一些的字符串查找算法,大體的思路是從右往左掃描,例如在txt = ABCBCDCDE中查找模式串pat = BCD,

ABCBCDCDE
BCD

從右往左,第一個比較的字符是 C 和 D ,不匹配,C 在 BCD 裏出現的所有位置中最靠右是 1,那麼 BCD 右移 1 位,比較 B 和 D ,

ABCBCDCDE
 BCD

不匹配,B 在 BCD裏出現的所有位置中最靠右是 0,那麼BCD右移 2 位,

ABCBCDCDE
   BCD

匹配成功,當然例子有些簡單,看完以下的具體規則後,就會消除你所有的顧慮 = =!
具體的規則如下:( i 是 txt 中的遊標,j 是 pat 中的遊標)

1. 如果失配字符不在 pat 中,那麼 pat 右移 j+1 個位置,也就是 i += j+1 繼續比較。這條應該是淺顯易懂,不懂得在紙上畫一下就知道了。

2. 如果失配字符在 pat 中,那麼 pat 右移,使得適配字符與 pat 中該字符出現的所有位置中最右的那個對齊,即右移 j - x 即 i += j - x ,x 即是最右位置。

3. 如果以上兩條不能使 i 增大,i += 1。

以上第 2 條的 x 可以通過預處理來提前計算好,計算的代碼如下:

int right[256];
memset(right, -1, sizeof(int) * 256);// 初始化爲-1

for (int k = 0; k < strlen(pat); ++k) {
    right[pat[k]] = k;
}

查找代碼如下:

int skip = 0;
for (int i = 0; i < strlen(txt) - strlen(pat); i += skip) {
    skip = 0;
    for (int j = (int)strlen(pat)-1; j >= 0; --j) {
        if (txt[i+j] != pat[j]) { // 字符匹配失敗
            skip = j - right[pat[j]];
            if (skip < 1) { // i 無法增大
                skip += 1;
            }
            break;
        }
    }
    if (skip == 0) { // 全部匹配成功
        return i;
    }
}

PS:可以根據KMP的思路,優化一下,即已經匹配過的,是不是有相同的串。

參考:《算法》第四版

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章