从BF算法到KMP算法(字符串匹配算法)

本文介绍了字符串匹配中的BF算法和KMP算法。BF算法时间复杂度为O(m*n),效率较低。而KMP算法通过next数组避免了不必要的回溯,提高了效率。文章详细解释了KMP算法的原理,并给出了如何计算next数组的例子,例如对于子串'ababc',next数组为{-1, 0, 0, 1, 2}。最后,文章提供了KMP算法的实现代码。" 128232929,8655615,CentOS7 源码编译 Bazel 教程,"['Linux', '源码编译', 'bazel构建工具', 'tensorflow框架', 'jdk环境']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

模式匹配:

给定两个字符串 s= "..."和 t="...",在主串 s 中查找子串 t 的过程称为模式匹配,匹配成功,则返回t在s中的位置,否则返回-1;

BF算法

  • 比较简单,相对效率比较低的字符串匹配算法,时间复杂度为O(m*n);
  • 基本思想:从主串 s 的第一个字符开始和子串 t 的第一个字符串开始比较,若相等,则继续比较二者后续字符; 若不相等,从主串的第二个字符和子串的第一个字符比较,重复上述步骤直至 s 或 t 中的字符比较完毕,这样很容易用代码描述出来
    public int bf(String str, String pattern) {
        char[] c = str.toCharArray();
        char[] p = pattern.toCharArray();
        int j = 0, k = 0;
        while (j < c.length && k < p.length) {
            if (c[j] == p[k]) {
                j++;
                k++;
            } else {
                j = j - k + 1;
                k = 0;
            }
        }
        if (k == p.length) {
            return j - k;
        } else
            return -1;
    }

KMP算法

BF算法简单,但效率较低,一种对BF算法做了比较大的改进的匹配算法是KMP算法,其基本思想是主串不回溯
  • 定义:Knuth-Morris-Pratt 字符串查找算法,简称为 “KMP算法”,常用于在一个文本串S内查找一个模式串P 的出现位置,这个算法由Donald Knuth、Vaughan Pratt、James H. Morris三人于1977年联合发表,故取这3人的姓氏命名此算法。
  • KMP算法的伪代码:
    1. 在串 s 和串 t 中分别设置比较的起始下标j和k;
    2. 重复下述操作,直到 s 或 t 的下一对字符;
      2.1 如果 s[j]等于 t[k],继续比较二者的下一对字符;
      2.2 否则将下标k回溯到next[k]的位置,即k=next[k];
      2.3 如果k=-1,则将下标j和k分别加1,准备下一趟比较;
    3. 如果 t 中多有字符均比较完毕,则返回匹配开始的位置,否则返回-1;
  • KMP算法难点就在于求next数组
  • next数组:为子串前缀集合和后缀集合中相同串中长度最大的数组集合,如下图

给出子串ababc,求出next数组

这里写图片描述

所以next[] = {-1, 0, 0, 1, 2}

实现代码如下

public int[] getNext(String p) {
        char[] t = p.toCharArray();
        int[] next = new int[t.length];
        int j = 0, k = -1;
        next[0] = -1;
        while (j < t.length - 1) {
            if ((k == -1) || (t[j] == t[k])) {
                next[++j] = ++k;
            } else
                k = next[k];
        }
        return next;
    }

KMP算法代码如下

public int kmp(String str, String pattern) {
        int next[] = getNext(pattern);
        char[] c = str.toCharArray();
        char[] p = pattern.toCharArray();
        int j = 0;// 主串位置
        int k = 0;// 模式串位置
        while (j < c.length && k < p.length) {
            if (k == -1 || c[j] == p[k]) {
                j++;
                k++;
            } else {
                k = next[k];
            }
        }
        if (k == p.length) {
            return j - k;
        } else
            return -1;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值