BoyerMoore 算法分析
创始人
2024-05-22 04:44:46
0

BoyerMoore 算法分析

匹配方向:从右向左开始匹配(从 ^ 的位置开始向左匹配):

aaaaaFaaaaaaaaaaaaaa
aaaaaaa^

一、坏字符匹配

坏字符:源串中第一个不匹配的字符就是坏字符(F 是坏字符):

aaaaaFaaaaaaaaaaaaa
aaaaaaa^

指针移动方式1

如果坏字符不在模式串中,则将指针向右移动“模式串长度”个字符,重新开始比较:

aaaaaFaaaaaFaaaaaaaaaaaaaa-------^

解释:当前模式串为 7 个 a,所以指针向右移动 7 个字符,目的是把 F 排除于下次比较的范围,如果移动不足 7 个字符,那么 F 就进入了下次比较的范围,由于 F 不在模式串中,让它进入比较范围没有意义。

重新比较之后,再次遇到坏字符 F:

aaaaaFaaaaaFaaaaaaaaaaaaaa^

指针继续向右移动 7 个字符:

aaaaaFaaaaaFaaaaaaaaaaaaaa-------^

完成匹配。

指针移动方式2

如果坏字符在模式串中,则需要在开始搜索之前,先找出模式串中各个字符最后出现的位置,然后记下该位置之后还有多少个字符。

aaaaabaaaaabccbcaaa
aabccbc

不看源串,只看模式串:
最右边的 a 之后有 5 个字符
最右边的 b 之后有 1 个字符
最右边的 c 之后有 0 个字符

记录该数据的目的是为了让指针能够跳转指定的长度,但是字符 c 所记录的数据 0 却没有使指针产生移动,所以最后一个字符不应该被记录,这样我们就需要使用前一个 c 的位置来记录,也就是 c 之后有 2 个字符,于是有了下面的跳转表:

如果遇到坏字符 a,则指针向右移动 5 个字符
如果遇到坏字符 b,则指针向右移动 1 个字符
如果遇到坏字符 c,则指针向右移动 2 个字符
如果遇到其它坏字符,则指针向右移动“模式串长度”个字符

开始比较:

aaaaabaaaaabccbcaaa
aabccbc^

遇到坏字符 a,指针向右移动 5 个字符:

aaaaabaaaaabccbcaaaaabccbc-----^

解释:跳转表中记录的遇到 a 应该跳转 5 个字符,目的是为了让源串中的坏字符 a 与模式串中的字符 a 对齐,如果跳转不足 5 个字符,则模式串中没有任何字符可以与源串中的 a 匹配上,因为 5 就是 a 在模式串中最后一次出现的位置,再往后就没有 a 了。

重新比较之后,再次遇到坏字符 b:

aaaaabaaaaabccbcaaaaabccbc^

根据跳转表中的记录,遇到 b 应该使指针向右移动 1 个字符:

aaaaabaaaaabccbcaaaaabccbc-^

重新比较之后,再次遇到坏字符 a:

aaaaabaaaaabccbcaaaaabccbc^

指针向右移动 5 个字符:

aaaaabaaaaabccbcaaaaabccbc-----^

完成匹配。

前面提到的跳转表,叫做“坏字符跳转表”,使用该表已经可以实现字符串快速查找。

二、好后缀匹配

为了进一步提高速度,BoyerMoore 算法还提出了另一种匹配方式,叫做“好后缀”匹配。

好后缀:匹配过程中已经匹配的部分就是好后缀(ba 是好后缀):

aaFbaaaaaba
aaaba^

指针移动方式1

如果好后缀在模式串中没有重复的部分(比如 ababa 中后缀 ba 就与前一个 ba 重复,这就不符合当前的情况),则将指针向右移动“模式串长度+已匹配长度”个字符,重新开始比较:

aaFbaaaaaba
-----aaaba-------^

说明:模式串刚好移动到源串上次匹配的 ba 之后,因为模式串向右移动的原则是“使源串中上次匹配的 ba 与模式串中离好后缀 ba 最近的某个 ba 对齐”,可是好后缀左边没有重复的 ba,所以无法与源串中的 ba 对齐,那就只能将模式串整个移动到源串的 ba 之后。

重新比较之后,没有出现好后缀:

aaFbaaaaabaaaaba^

只能向右移动一个字符:

aaFbaaaaaba-aaaba-^

完成匹配。

指针移动方式2

如果好后缀在模式串中有重复的部分,则将指针向右移动“好后缀到最后一个重复部分之间的距离+已匹配的长度”个字符,重新开始比较:

aaaaaaFbabaCbaCba
abaCbaCba^

因为好后缀 ba 前面有重复的 ba,所以需要将离好后缀最近的 ba 与源串中上次匹配的 ba 对齐:

aaaaaaFbabaCbaCba
---abaCbaCba-----^

此时没有匹配的后缀,只能将模式串向右移动一个字符:

aaaaaaFbabaCbaCba-abaCbaCba-^

此时仍然没有匹配的后缀,只能将模式串向右移动一个字符:

aaaaaaFbabaCbaCba-abaCbaCba-^

此时出现好后缀 baCba:

aaaaaaFbabaCbaCbaabaCbaCba^

这个好后缀比较特殊,它是有重复部分的,只不过前后重叠在一起:

aaaaaaFbabaCbaCbaabaCbaCba^^^^^^^^^^^

此时需要将重复部分移动到源串中上次匹配的 baCba 位置:

aaaaaaFbabaCbaCba---abaCbaCba--------^

完成匹配。

如果有多个连续的重复部分,则可以一次跳过所有这些重复部分,例如:

aaaaaaaFbababababa
bababababa^

按照一般思路,应该将离好后缀最近的一个 ba 与源串中上次匹配的 ba 对齐,但是因为这些重复 ba 是相连的,既然 F 与好后缀 ba 之前的 a 不匹配,那么所有相连的 ba 前一个字符都是 a,都不可能与 F 匹配,所以可以一次跳过所有相连的 ba,将最左边的重复 ba 与源串中上次匹配的 ba 对齐即可:

aaaaaaaFbababababa
--------bababababa---------^

完成匹配。

好后缀也有一个跳转表,只需要在搜索之前计算好,就可以实现快速搜索,好后缀的跳转表计算起来要比坏字符复杂一些。

BoyerMoore 算法同时使用“坏字符”和“好后缀”两种跳转方式,每次遇到坏字符时,也会出现好后缀,然后选择两种跳转方式中跳转距离更远的作为本次跳转长度。

在 FPC 的 StrUtils 单元中有 BoyerMoore 算法的实现,可以参考。

相关内容

热门资讯

关于 “接纳”,的名人故事? 关于 “接纳”,的名人故事?楚霸王项羽就是因为没有接纳别人的意见在鸿门宴上没有杀死刘备所以才有后来的...
听说龙之谷2要出,龙之谷1和龙... 听说龙之谷2要出,龙之谷1和龙之谷2想通吗?龙之谷2还早得很 现在说什么都是空头支票
不孕不育哪家医院的好? 不孕不育哪家医院的好?在泉州的话,玛丽医院还不错的,是一家不孕不育专科医院,技术应该蛮不错的。建议到...
几百块钱的小生意,15个投资几... 生活中不缺少赚钱的机会,只有找钱的眼睛。能赚钱的都有一双眼睛去发现。今天边肖将带你去看那些有利可图的...
万籁俱静的近义词 万籁俱静的近义词拼音万籁俱静 ( wàn lài jù jing )出处唐·常建《题余扮破山寺后禅院...
全国新产品厂家招代理(个人在哪... 随着人们对健康问题越来越重视,对中医药防治疾病的认识也越来越强,大健康行业在中国的规模也在不断扩大。...
云南农村信用社贷款条件(农村创... 如今,贷款模式不仅在城市常见,在农村也很常见。很多朋友选择贷款是因为临时资金周转不够,而农民一般选择...
农村镇上适合做的生意(2020... 现在很难赚钱,农村更难赚钱。这是所有人的共识,但对于农村人来说,生活的根其实在农村。我们要紧跟政策,...
儿童游乐园投资多少(开一个儿童... 现在儿童公园的发展如火如荼,大家都想把注意力转向儿童公园的投资。那么大家都有一个投资儿童公园的问题,...
现在开什么店最赚钱,加盟什么便... 现在想自己创业的人越来越多了。毕竟谁想一直给别人打工,谁又累又没多少钱,还不如自己开店当老板。那么,...