来源:《算法》第四版 第五章
1、Boyer-Moore算法简述
和KMP算法中的实现相似,它也需要一个记录重启位置的数组。Boyer和Moore给出的另一种从右向左扫描模式字符串的更有效的方法。这个方法非常的高效。比较次数会减少许多。
2、Boyer-Moore算法步骤
1、起点
要实现启发式地处理不匹配的字符,我们使用数组 right[]
记录字母表中的每个字符在模式中出现的最靠右的地方(如果字符在模式中不存在则表示为-1)。这个值揭示了如果该字符出现在文本中且在查找时造成了一次匹配失败,应该向右跳跃多远。
要将 right[]
数组初始化,首先将所有元素的值设为-1,然后对于 0 到 M-1 的 j ,将 right[pat.charAt(j)
设为 j 。
2、子字符串的查找
我们用一个索引 i 在文本中从左向右移动,用另一个索引 j 在模式中从右向左移动。内循环会检查正文和模式字符串在位置 i 是否一致。如果从 M-1 到 0 的所有j, txt.charAt(i+j)
都和 pat.charAt(j)
相等,那么就找到了一个匹配。否则匹配失败,就会遇到以下三种情况。
- 如果造成匹配失败的字符不包含在模式字符串中,将模式字符串向右移动 j+1 个位置(即,将 i 增加 j+1)。小于这个偏移量只可能使该字符与模式中的某个字符重叠。事实上,这次移动也会将模式字符串前面一部分已知的字符和模式结尾的一部分已知字符对齐。通过预先计算一张类似于KMP算法的表格,还可以将i值变得更大(请见图5.3.12)。
- 如果造成匹配失败的字符包含在模式字符串中,那就可以使用
right[]
数组来将模式字符串和文本对齐,使得该字符和它在模式字符串中出现的最右位置相匹配。和刚才一样,小于这个偏移量只可能使该字符和模式中的与它无法匹配的字符(比它出现的最右位置更靠右的字符)重叠。我们可以用一张类似于KMP算法的表格将1变得更大。- 如果这种方式无法增大 i ,那就直接将 i 加1来保证模式字符串至少向右移动了一个位置。
3、总结
完整的Boyer-Moore算法预计算了模式宇符串与自身的不匹配情况(和KMP算法的方式类似)并为最坏情况提供了线性级别的运行时间保证。我们在这里省略了算法的计算,因为在一般的应用程序中对不匹配宇符的启发式处理已经可以控制算法的性能。