BM算法是基于后缀的算法,所以在移动模式串的时候是从左到右,而在比较的时候是从右到左。
BM算法核心是两个并行算法(好后缀和坏字符),这两种算法的目的就是为了每次让模式串移动尽可能大的距离。
关于好后缀和坏字符的定义如下:
例主串和模式串如下
主串 : mahtavaatalomaisema omalomailuun
模式串: maisemaomaloma
好后缀:模式串中的aloma为“好后缀”。
坏字符:主串中的“t”为坏字符。
BM算法预先计算三个shift函数d1,d2,d3,他们分别对应于以下的三种情况。这三种情况都假设已经读入了一个既是文本串的后缀,又是模式串后缀的字符串u。并且读入的下一个文本字符x与模式串的下一个字符y不相等。
(1)有好后缀,即后缀u在模式串p中的另一个位置出现。假设另一个位置的u的最右下标为j,模式串的长度为m。则需要将窗口移动m-j个字符。此时,shift(d1)计算模式串的每一个后缀到它下一个出现位置的距离。如果p的后缀u不在p中重复出现,那么d1(u)被置为整个模式串的长度。
(2)有部分后缀,即存在最大匹配串,u的后缀v是模式串p的一个前缀。此时d2(u)表示既是p的前缀,同时也是u的后缀的最长字符串v的长度。
(3)坏字符。模式串在文本字符y出不能成功匹配。如果用d1函数移动,若对应的模式串的位置还是不是y,就进行了不必要的验证。shift函数d3就是用来保证下一次验证时文本字符y一定与模式串中的一个字符y匹配。d3(y)表示y 在模式串中的最右出现位置到模式串末尾的距离。如果不出现,d3(y)就设置为m。
刚才说过,本BM算法就是好后缀与坏字符的并行。
好后缀算法
如果程序匹配了一个好后缀, 并且在模式中还有另外一个相同的后缀, 那
把下一个后缀移动到当前后缀位置。好后缀算法有两种情况:
Case1:模式串中有子串和好后缀安全匹配,则将最靠右的那个子串移动到好后缀的位置。继续进行匹配。
Case2:如果不存在和好后缀完全匹配的子串,则在好后缀中找到具有如下特征的最长子串,使得P[m-s…m]=P[0…s]。说不清楚的看图。
坏字符算法
当出现一个坏字符时, BM算法向右移动模式串, 让模式串中最靠右的对应字符与坏字符相对,然后继续匹配。坏字符算法也有两种情况。
Case1:模式串中有对应的坏字符时,见图。
Case2:模式串中不存在坏字符。见图。
移动规则
BM算法的移动规则是:
将概述中的++j,换成j+=MAX(shift(好后缀),shift(坏字符)),即
BM算法是每次向右移动模式串的距离是,按照好后缀算法和坏字符算法计算得到的最大值。