博主介绍: ✌博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家✌
💕💕 感兴趣的同学可以收藏关注下 ,不然下次找不到哟💕💕
1、什么是 Boyer-Moore
Boyer-Moore 是一种字符串匹配算法,用于在一个文本串中查找一个模式串的出现位置。该算法由 Robert S. Boyer 和 J Strother Moore 于 1977 年提出,是一种高效的字符串匹配算法之一。
Boyer-Moore 算法的核心思想是利用模式串中的字符出现规律来跳过尽可能多的比较操作,从而提高匹配的效率。它分为两个阶段:预处理阶段和匹配阶段。
在预处理阶段,算法会根据模式串的内容构建两个规则表:坏字符规则表和好后缀规则表。坏字符规则表记录了每个字符在模式串中最后一次出现的位置,用于确定坏字符的移动距离;好后缀规则表记录了模式串中每个后缀子串的匹配位置,用于确定好后缀的移动距离。
在匹配阶段,算法从文本串的开头开始与模式串进行匹配。当发现不匹配的字符时,根据坏字符规则表和好后缀规则表来确定模式串的移动距离,以尽可能地跳过不可能匹配的位置。通过不断地向后滑动模式串,直到找到匹配或完全不匹配为止。
Boyer-Moore 算法在处理大型文本串时具有较高的效率,尤其是在模式串较长且包含重复字符时。它的时间复杂度为 O(n/m),其中 n 是文本串的长度,m 是模式串的长度。
2、Boyer-Moore 的优缺点
Boyer-Moore 算法具有以下优点:
-
高效性:Boyer-Moore 算法在大多数情况下比其他字符串匹配算法更快。它利用了模式串中的字符出现规律,能够跳过尽可能多的比较操作,从而提高匹配的效率。
-
预处理快速:Boyer-Moore 算法在预处理阶段构建坏字符规则表和好后缀规则表的时间复杂度为 O(m),其中 m 是模式串的长度。这使得算法在匹配阶段能够快速定位模式串的移动距离。
-
适用性广泛:Boyer-Moore 算法适用于各种不同类型的模式串,包括长模式串和包含重复字符的模式串。它在处理大型文本串时表现出色。
Boyer-Moore 算法的缺点包括:
-
预处理空间消耗:Boyer-Moore 算法在预处理阶段需要构建坏字符规则表和好后缀规则表,这可能会消耗较多的额外空间,尤其是对于较长的模式串。
-
不适用于部分应用场景:Boyer-Moore 算法在某些特定情况下可能不如其他算法,例如当模式串中包含大量重复的字符时,算法的效率可能不如 Rabin-Karp 算法。
-
需要额外的预处理时间:Boyer-Moore 算法在匹配之前需要进行预处理,构建坏字符规则表和好后缀规则表,这可能会增加算法的启动时间。
综上所述,Boyer-Moore 算法在大多数情况下具有较高的匹配效率和适用性广泛的优点,但在某些特定情况下可能存在一些缺点。在实际应用中,需要根据具体的场景和需求选择合适的字符串匹配算法。
3、Boyer-Moore 的应用场景
Boyer-Moore 算法在字符串匹配领域有广泛的应用场景,特别适用于以下情况:
-
长模式串匹配:当模式串较长时,Boyer-Moore 算法的效率比其他字符串匹配算法更高。它通过坏字符规则和好后缀规则的匹配跳过尽可能多的比较操作,从而实现快速的匹配。
-
大型文本串匹配:对于大型文本串,Boyer-Moore 算法能够利用坏字符规则和好后缀规则快速定位模式串的移动距离,从而提高匹配效率。
-
包含重复字符的模式串匹配:Boyer-Moore 算法对于包含重复字符的模式串的匹配效果较好。它通过坏字符规则和好后缀规则的匹配,能够跳过重复字符的比较操作,从而提高匹配速度。
-
文本搜索引擎:Boyer-Moore 算法被广泛应用于文本搜索引擎中,用于实现关键字的快速匹配和搜索。它能够高效地处理大量的文本数据,并返回匹配结果。
总的来说,Boyer-Moore 算法适用于长模式串匹配、大型文本串匹配、包含重复字符的模式串匹配以及文本搜索引擎等应用场景。它通过利用坏字符规则和好后缀规则,能够快速定位模式串的移动距离,从而提高匹配效率。
4、Boyer-Moore 的原理
Boyer-Moore 算法是一种高效的字符串匹配算法,它利用了两个规则来快速定位模式串在文本串中的位置,从而提高匹配效率。这两个规则分别是坏字符规则(Bad Character Rule)和好后缀规则(Good Suffix Rule)。
-
坏字符规则:
- 当发现模式串中的某个字符与文本串中的字符不匹配时,可以将模式串向右移动,使得该不匹配字符对齐文本串中的下一个字符。
- 如果文本串中的字符在模式串中不存在,那么可以将模式串整体向右移动,直接跳过该字符。
-
好后缀规则:
- 当模式串中的某个后缀与文本串中的子串匹配时,可以将模式串向右移动,使得该后缀对齐文本串中的子串。
- 如果文本串中的子串在模式串中找不到匹配的后缀,那么可以将模式串整体向右移动,直接跳过该子串。
Boyer-Moore 算法利用这两个规则来选择移动的距离,以尽量减少比较操作的次数。具体实现时,可以预先计算出每个字符在模式串中最右出现的位置,以及每个后缀在模式串中的最右出现位置。然后根据坏字符规则和好后缀规则,选择移动的距离。
通过利用坏字符规则和好后缀规则,Boyer-Moore 算法能够快速定位模式串在文本串中的位置,从而提高字符串匹配的效率。它在实际应用中被广泛使用,特别适用于长模式串匹配和大型文本串匹配的场景。
5、Boyer-Moore 的使用案例
Boyer-Moore算法在字符串匹配领域有着广泛的应用,以下是一些使用Boyer-Moore算法的案例:
-
文本编辑器中的查找功能:许多文本编辑器使用Boyer-Moore算法来实现快速查找功能。当用户在文本中输入关键字进行查找时,编辑器可以利用Boyer-Moore算法快速定位匹配的位置,提高查找效率。
-
字符串搜索引擎:搜索引擎需要对大量的文本进行索引和搜索。Boyer-Moore算法可以用于字符串搜索引擎中的关键字匹配,帮助搜索引擎快速定位匹配的文档。
-
文件压缩和解压缩:Boyer-Moore算法可以应用于文件压缩和解压缩算法中的字符串匹配部分。通过使用Boyer-Moore算法,可以快速定位重复的字符串,从而实现高效的压缩和解压缩。
-
数据库系统中的模式匹配:在数据库系统中,模式匹配是一个重要的操作。Boyer-Moore算法可以用于模式匹配中的字符串匹配部分,帮助数据库系统快速定位匹配的数据。
总之,Boyer-Moore算法在字符串匹配领域有着广泛的应用,能够提高字符串匹配的效率。无论是在文本编辑器、搜索引擎、文件压缩和解压缩,还是数据库系统中,Boyer-Moore算法都可以发挥重要作用。
6、使用 Java 实现 Boyer-Moore
package com.pany.camp.algorithm;
/**
*
* @description: Boyer-Moore 字符串匹配算法
* @copyright: @Copyright (c) 2022
* @company: Aiocloud
* @author: pany
* @version: 1.0.0
* @createTime: 2023-06-28 21:17
*/
public class BoyerMoore {
private int[] right;
private String pattern;
public BoyerMoore(String pattern) {
this.pattern = pattern;
int patternLength = pattern.length();
int alphabetSize = 256; // ASCII字符集大小
right = new int[alphabetSize];
for (int i = 0; i < alphabetSize; i++) {
right[i] = -1; // 初始化为-1,表示字符不在模式中
}
for (int i = 0; i < patternLength; i++) {
right[pattern.charAt(i)] = i; // 记录每个字符在模式中最右出现的位置
}
}
public int search(String text) {
int textLength = text.length();
int patternLength = pattern.length();
int skip;
for (int i = 0; i <= textLength - patternLength; i += skip) {
skip = 0;
for (int j = patternLength - 1; j >= 0; j--) {
if (pattern.charAt(j) != text.charAt(i + j)) {
skip = Math.max(1, j - right[text.charAt(i + j)]);
break;
}
}
if (skip == 0) {
return i; // 找到匹配的位置
}
}
return -1; // 未找到匹配的位置
}
public static void main(String[] args) {
String text = "ABABABABCDABABCABAB";
String pattern = "ABABCABAB";
BoyerMoore bm = new BoyerMoore(pattern);
int index = bm.search(text);
if (index != -1) {
System.out.println("Pattern found at index " + index);
} else {
System.out.println("Pattern not found");
}
}
}
输出如下:
Pattern found at index 10
Process finished with exit code 0
💕💕 本文由激流原创 💕💕喜欢的话记得点赞收藏啊