- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
BM算法详解及Java实现
BM算法详解及Java实现
1977年,德克萨斯大学的Robert S. Boyer教授和J Strother Moore教授发明了一种新的字符串匹配算法:Boyer-Moore算法,简称BM算法。该算法从模式串的尾部开始匹配,且拥有在最坏情况下O(N)的时间复杂度。在实践中,比KMP算法的实际效能高。
后缀匹配,是指模式串的比较从右到左,模式串的移动也是从左到右的匹配过程,经典的BM算法其实是对后缀暴力匹配算法的改进。所以还是先从最简单的后缀暴力匹配算法开始。下面直接给出伪代码,注意这一行代码:j++;BM算法所做的唯一的事情就是改进了这行代码,即模式串不是每次移动一步,而是根据已经匹配的后缀信息,从而移动更多的距离。
/**
* 后缀暴力匹配
*
* @param T 正文字符数组
* @param P 模式字符数组
* @return 匹配位置
*/
public static int bf(char[] T, char[] P) {
for (int j = 0; j = T.length - P.length; j++) {
int i = P.length - 1;
for (; i = 0 P[i] == T[i + j]; --i) {
}
if (i 0) {
return j;
}
}
return -1;
}
BM算法介绍
为了实现更快移动模式串,BM算法定义了两个规则,好后缀规则和坏字符规则,如下图可以清晰的看出他们的含义。利用好后缀和坏字符可以大大加快模式串的移动距离,不是简单的++j,而是j+=max (shift(好后缀), shift(坏字符))。
下面举例说明BM算法。例如,给定文本串“HERE IS A SIMPLE EXAMPLE”,和模式串“EXAMPLE”,现要查找模式串是否在文本串中,如果存在,返回模式串在文本串中的位置。
首先,文本串与模式串头部对齐,从尾部开始比较。S与E不匹配。这时,S就被称为坏字符(bad character),即不匹配的字符,它对应着模式串的第6位。且S不包含在模式串EXAMPLE之中(相当于最右出现位置是-1),这意味着可以把模式串后移6-(-1)=7位,从而直接移到S的后一位。
依然从尾部开始比较,发现P与E不匹配,所以P是坏字符。但是,P包含在模式串EXAMPLE之中。因为“P”这个“坏字符”对应着模式串的第6位(从0开始编号),且在模式串中的最右出现位置为4,所以,将模式串后移6-4=2位,两个P对齐。
?依次比较,得到 “MPLE”匹配,称为好后缀(good suffix),即所有尾部匹配的字符串。注意,MPLE、PLE、LE、E都是好后缀。
?
发现“I”与“A”不匹配:“I”是坏字符。如果是根据坏字符规则,此时模式串应该后移2-(-1)=3位。
继续从尾部开始比较,“”与“E”不匹配,因此“”是“字符”,根据“字符规则”,后移 6 - = 5位。
?
依次从尾部开始比较,
由上可知,BM算法不仅效率高,而且构思巧妙,容易理解。
先来看如何根据坏字符来移动模式串,shift(坏字符)分为两种情况:
坏字符没出现在模式串中,这时可以把模式串移动到坏字符的下一个字符,继续比较,如下图:
坏字符出现在模式串中,这时可以把模式串第一个出现的坏字符和母串的坏字符对齐,当然,这样可能造成模式串倒退移动,如下图:
此处配的图是不准确的,因为显然加粗的那个b并不是”最靠右的”b。而且也与下面给出的代码冲突!我看了论文,论文的意思是最右边的。当然了,尽管一时大意图配错了,论述还是没有问题的,我们可以把图改正一下,把圈圈中的b改为字母f就好了。接下来的图就不再更改了,大家心里有数就好。
为了用代码来描述上述的两种情况,设计一个数组bmBc[k],表示坏字符‘k’在模式串中出现的位置距离模式串末尾的最大长度,那么当遇到坏字符的时候,模式串可以移动距离为: shift(坏字符) = bmBc[T[i]]-(m-1-i)。如下图:
?数组bmBc的创建非常简单,直接贴出代码如下:
/**
* 坏字符忽略映射
*
* @param T 模式字符数组
* @return 坏字符忽略映射
*/
public static int[] bmBc(char[] T) {
// 初始忽略数组
int[] bmBc = new int[65536];
// 填充坏字符序号
Arrays.fill(bmBc, -1);
// 填充好字符序号(以最后位置为准)
int m = T.length;
for (int i = 0; i m; i++) {
bmBc[T[i]] = m - 1 - i;
}
原创力文档


文档评论(0)