目录
在模式匹配问题中,给定长度为 n 的文本字符串 T 和 长度为 m 的模式字符串 P,需要确定 P 是否是 T 的一个子串。如果是,则找到 P 在 T 中的开始位置的索引,或者从 T 中找到所有 P 的开始位置的索引。
Horspool 算法即 Boyer Moore Horspool 算法,是 Boyer Moore 算法的简化版本。
Horspool 算法通过增加两个启发式算法来提升穷举算法的运行时间。
- looking-glass heuristic(镜像启发式):当比较 P 相对于 T 可能的位置时,从 P的尾部开始比较,然后从后向前移动直到 P 的头部。
- character-jump heuristic(字符跳跃启发式):当比较 P 相对于 T 可能的位置时,对于 T[i]=c, 如果 P 中任何位置都不包含 c,则将 P 完全移动到 T[i] 之后(因为 T[i] 不能匹配 P 中的任何字符);否则,直到 P 中出现字符 c 且与 T[i] 一致才移动 P。
Horspool 算法最坏的情况下运行时间是 O(nm),最好情况下是 O(m + n)。
- text = "hi hold world"
- pattern = "world"
- def horspool(text, pattern):
- n, m = len(text), len(pattern)
- if m == 0:
- return 0
-
- last = dict()
- for k in range(m):
- last[pattern[k]] = k
-
- i = m - 1
- k = m - 1
- while i < n:
- if text[i] == pattern[k]:
- if k == 0:
- return i
- else:
- i -= 1
- k -= 1
- else:
- j = last.get(text[i], -1)
- i += m - min(k, j + 1)
- k = m - 1
- return -1
-
-
- def main():
- text = "hi hold world"
-
- pattern1 = "world"
- print(horspool(text, pattern1))
-
- pattern2 = "python"
- print(horspool(text, pattern2))
-
-
- if __name__ == "__main__":
- main()
- package org.example;
-
- import java.util.HashMap;
-
- public class Horspool {
-
- public static int horspool(String text, String pattern) {
- int n = text.length();
- int m = pattern.length();
- if (m == 0) {
- return 0;
- }
-
- HashMap
last = new HashMap(); - for (int k = 0; k < m; k++) {
- last.put(pattern.charAt(k), k);
- }
-
- int i = m - 1;
- int k = m - 1;
- while (i < n) {
- if (text.charAt(i) == pattern.charAt(k)) {
- if (k == 0) {
- return i;
- } else {
- i -= 1;
- k -= 1;
- }
- } else {
- int j = last.containsKey(text.charAt(i)) ? last.get(text.charAt(i)) : -1;
- i += m - Math.min(k, j + 1);
- k = m - 1;
- }
- }
- return -1;
- }
-
- public static void main(String[] args) {
- String text = "hi hold world";
-
- String pattern1 = "world";
- System.out.println(horspool(text, pattern1));
-
- String pattern2 = "python";
- System.out.println(horspool(text, pattern2));
- }
- }
- #include
- #include
-
- int min(int a, int b) {
- return a < b ? a : b;
- }
-
- int horspool(const char *text, const char *pattern) {
- int n = strlen(text);
- int m = strlen(pattern);
-
- int last[256];
- for (int k = 0; k < 256; k++) {
- last[k] = -1;
- }
- for (int k = 0; k < m; k++) {
- last[pattern[k]] = k;
- }
-
- int i = m - 1;
- int k = m - 1;
- while (i < n) {
- if (text[i] == pattern[k]) {
- if (k == 0) {
- return i;
- } else {
- i--;
- k--;
- }
- } else {
- int j = last[text[i]];
- i += m - min(k, j + 1);
- k = m - 1;
- }
- }
- return -1;
- }
-
- int main() {
- char text[] = "hi hold world";
-
- char pattern1[]= "world";
- printf("%d\n", horspool(text, pattern1));
-
- char pattern2[] = "python";
- printf("%d\n", horspool(text, pattern2));
- }
- #include
- #include
-
- using namespace std;
-
- int horspool(string text, string pattern) {
- int n = text.size();
- int m = pattern.size();
- if (m == 0) {
- return 0;
- }
-
- map<char, int> last;
- for (int k = 0; k < m; k++) {
- last[pattern[k]] = k;
- }
-
- int i = m - 1;
- int k = m - 1;
- while (i < n) {
- if (text[i] == pattern[k]) {
- if (k == 0) {
- return i;
- } else {
- i--;
- k--;
- }
- } else {
- int j = last.find(text[i]) != last.end() ? last[text[i]] : -1;
- i += m - min(k, j + 1);
- k = m - 1;
- }
- }
- return -1;
-
- }
-
- int main() {
- string text = "hi hold world";
- string pattern1 = "world";
- cout << horspool(text, pattern1) << endl;
-
- string pattern2 = "python";
- cout << horspool(text, pattern2) << endl;
- }