当前位置:首页 > 嵌入式 > 嵌入式分享

三、BM 算法实现与代码解析

(一)预处理阶段

坏字符表构建:坏字符表(Bad Character Table)的构建是预处理阶段的关键任务之一。其目的是为了在匹配过程中,当遇到不匹配的字符(即坏字符)时,能够快速确定模式串应该向右滑动的距离。在 Python 中,我们可以使用哈希表(字典)来实现这一功能 。

def build_bad_char_table(pattern):

bad_char = {}

for i in range(len(pattern) - 1):

bad_char[pattern[i]] = i

return bad_char

这段代码通过遍历模式串,将每个字符作为键,其在模式串中的位置作为值,存储在哈希表bad_char中。例如,对于模式串 "ABABC",哈希表中会记录'A': 0, 'B': 1, 'C': 4(这里只记录到倒数第二个字符,因为最后一个字符在匹配时用于判断是否完全匹配,不需要单独记录其位置)。这种方式使得在匹配过程中查询坏字符的位置时间复杂度为\(O(1)\),极大地提高了匹配效率。

除了哈希表,也可以使用数组来存储坏字符的位置信息。如果字符集是有限且已知的,例如 ASCII 字符集(共 128 个字符),可以创建一个大小为 128 的数组bc,初始值全部设为 -1 。然后遍历模式串,对于每个字符pattern[i],将bc[ord(pattern[i])]设置为i。这样在查询时,通过bc[ord(bad_character)]即可获取坏字符在模式串中的位置,同样支持\(O(1)\)时间复杂度的字符查询。

好后缀表构建:好后缀表(Good Suffix Table)的构建相对复杂,它需要考虑模式串中后缀与前缀的匹配关系,以及后缀在模式串中的其他匹配位置。构建好后缀表的核心逻辑在于通过后缀匹配和前缀检查,生成每个位置对应的滑动距离。

def build_good_suffix_table(pattern):

m = len(pattern)

suffix = [-1] * m

prefix = [False] * m

for i in range(m - 1):

j = i

while j >= 0 and pattern[j] == pattern[m - 1 - i + j]:

j -= 1

suffix[m - 1 - i] = j + 1

for i in range(m - 1):

if suffix[i] == 0:

prefix[m - 1 - i] = True

for i in range(1, m):

j = m - 1 - suffix[i]

prefix[j] = True

good_suffix = [m] * m

for i in range(m - 2, -1, -1):

if prefix[i]:

good_suffix[i] = m - 1 - i

else:

good_suffix[i] = good_suffix[m - 1 - suffix[i]]

return good_suffix

在这段代码中,首先通过一个双重循环计算suffix数组,suffix[i]表示从模式串末尾开始长度为i + 1的后缀,其最长匹配后缀的长度(即从模式串开头开始的相同子串长度)。例如,对于模式串 "ABABC",当i = 0时,后缀为 "C",其最长匹配后缀长度为 0;当i = 1时,后缀为 "BC",其最长匹配后缀长度为 0;当i = 2时,后缀为 "ABC",其最长匹配后缀长度为 3(因为模式串开头的 "ABC" 与之匹配),所以suffix[2] = 3

然后,通过检查suffix数组,标记出哪些位置的后缀是模式串的前缀,存储在prefix数组中。最后,根据suffixprefix数组生成good_suffix数组,good_suffix[i]表示当在位置i匹配失败时,根据好后缀规则模式串应该向右滑动的距离。如果prefix[i]True,说明从位置i开始的后缀是模式串的前缀,此时滑动距离为模式串长度减去i;否则,滑动距离为good_suffix[m - 1 - suffix[i]],即根据之前计算的相同后缀的滑动距离来确定。

(二)匹配阶段

匹配阶段是 BM 算法的核心执行部分,它从主串的起始位置开始,将模式串与主串进行对齐,并从模式串的末尾字符开始向前比较。

def boyer_moore_search(text, pattern):

n = len(text)

m = len(pattern)

bad_char = build_bad_char_table(pattern)

good_suffix = build_good_suffix_table(pattern)

s = 0

while s <= n - m:

j = m - 1

while j >= 0 and text[s + j] == pattern[j]:

j -= 1

if j < 0:

print(f"Pattern found at position {s}")

s += good_suffix[0]

else:

bad_char_shift = j - bad_char.get(text[s + j], -1)

good_suffix_shift = good_suffix[j]

s += max(bad_char_shift, good_suffix_shift)

在上述代码中,外层循环控制模式串在主串中的滑动位置s。每次循环开始时,将模式串的末尾字符与主串中对应的字符进行比较(通过内层循环实现)。如果从模式串末尾开始的所有字符都与主串中对应的字符匹配(即j < 0),则说明找到了一个匹配位置,打印出匹配位置,并根据好后缀表中的第一个值(good_suffix[0])滑动模式串,因为此时整个模式串都匹配,按照好后缀规则移动可以继续寻找下一个可能的匹配位置 。

如果在比较过程中发现不匹配的字符,即坏字符,根据坏字符规则计算滑动距离bad_char_shift,同时根据好后缀规则计算滑动距离good_suffix_shift。然后取这两个滑动距离中的较大值,将模式串向右滑动相应的距离,继续下一轮匹配。这样,通过不断地利用坏字符规则和好后缀规则,BM 算法能够在主串中快速定位模式串的所有匹配位置,避免了大量不必要的字符比较操作,从而实现高效的字符串匹配。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭