模式匹配算法 - Horspool

目录

1. 问题定义

2. Horspool 算法

3. 图解 Horspool

4. 代码实现

4.1. Python

4.2. Java

4.3. C

4.4. C++


1. 问题定义

        在模式匹配问题中,给定长度为 n 的文本字符串 T 和 长度为 m 的模式字符串 P,需要确定 P 是否是 T 的一个子串。如果是,则找到 P 在 T 中的开始位置的索引,或者从 T 中找到所有 P 的开始位置的索引。

2. Horspool 算法

        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)。

3. 图解 Horspool

text = "hi hold world"
pattern = "world"

 

4. 代码实现

 

4.1. Python

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()

4.2. Java

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<Character, Integer> last = new HashMap<Character, Integer>();
        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));
    }
}

4.3. C

#include <stdio.h>
#include <string.h>

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));
}

4.4. C++

#include <iostream>
#include <map>

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;
}

  • 5
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Encarta1993

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值