前面学习了sunday算法,BM算法也是跟sunday算法有相似之处。
BM算法有3个关键点,如果这三个关键点都理解了,那么这个算法就不是难题了。
1、从右向左匹配。
顾名思义,就是从最后一个字符开始向前匹配。例如
string: j k l i p j h d a b c z m w i j h d .....
pattern: w i j h
我们开始时看第四个位置o与pattern里面最后一个h是否匹配。接着倒数第三个位置与pattern相应的位置是否匹配。(sunday算法没有这个要求,可以向前也可以向后)。
2、坏字符规则。
当我们从右向左匹配的时候,如果一个字符没有匹配时候,我们分两种情况来探讨:
第一种情况,第一次不匹配的字符在pattern中,这时候我们要找到这个字符在pattern中最右的位置那个,让它与这个对齐。我们看例子:
string: j k l i p j h d a b c z m w i j h d .....
pattern: w i j h
移动后如下:
string: j k l i p j h d a b c z m w i j h d .....
pattern: w i j h
如果pattern是这样的。
string: j k l i p j h d a b c z m w i j h d .....
pattern: i i j k
那么移动之后就变成了
string: j k l i p j h d a b c z m w i j h d .....
pattern: i i j k
与最右边的匹配。
第二种情况,第一次不匹配的字符不在pattern中,那么直接要跳过这个字符。
string: j k l o d n a b d y a b m ....
pattern: j k r o
第一次不匹配的字符在l处,同时l也不在pattern中。那么整个pattern移动到l之后。
变换后:
string: j k l o d n a b d y a b m ....
pattern: j k r o
3、好后缀原则
这个不好理解。我们直接作图在图上来解释。
string: a b c b a d f t b c f a q v t b c e...
pattern: c b c a b c e a b c
这里面,bc是一个好后缀。但是在a的时候不匹配了。这时候我们查找pattern里面是否还有好后缀一样的。发现pattern里面有两个。一个是开始的cbc,另外一个是中间的abc。我们一定要舍弃好后缀前面一样的字符的那个后缀。也就是abc这个后缀我们要舍弃不用(用了也白用)。就将cbc里面的bc与现在的bc位置对齐。
string: a b c b a d f t b c f a q v t b c e...
pattern: c b c a b c e a b c
还有一种情况就是好后缀找到后,但是pattern里面没有同样的后缀了。这时候该怎么办呢?看下面的:
string: a b c b a d f t b c f a q v t b c e...
pattern: b c c a b c e t b c
tbc是一个好后缀,但是pattern里面没有一样的字符串了。这时候我们就在pattern前面找与tbc最长后缀相同的字符串(如果有多个,就要最左边的那个)。bc是一个,就在第一个位置。就是它了,把它移到bc位置。
string: a b c b a d f t b c f a q v t b c e...
pattern: b c c a b c e t b c
OK 了,如果你对这三个都熟悉了。那么BM算法就是这样了。
相应的代码网上有很多种,我这不在写了。有兴趣的朋友可以去其他位置看看。