当前位置:首页 > 技术 > 正文内容

KMP 字符串匹配算法详解

访客 技术 2026年6月8日 1

KMP 算法是一种高效的字符串匹配方法,用于在主文本中查找模式串的位置。该算法避免了传统暴力匹配中不必要的回溯操作,从而提升了整体性能。

在进行字符串匹配时,若当前字符不匹配,KMP 利用已知的部分匹配信息决定模式串应向右滑动多少位,而不是简单地逐位移动。这种方式显著减少了重复比较的次数。

基本思想

考虑在字符串 T 中查找模式串 P 的过程。假设当前比较到 T[i] 和 P[j] 不一致:

  • 传统做法是将模式串向右移动一位,并重置 j=0。
  • KMP 做法则是根据预先计算好的"部分匹配表"(通常称为 next 数组),仅调整 j 的位置,保持 i 不变。

构建 next 数组

next 数组记录的是每个位置 j 对应的最长公共前后缀长度。具体来说,next[j] 表示当 P[j] 与 T[i] 失配时,j 应该跳转到的新位置。

构造 next 数组的过程本质上是在模式串自身内部查找最长相等前后缀:

public static int[] buildNextArray(String pattern) {
    char[] p = pattern.toCharArray();
    int[] next = new int[p.length];
    next[0] = -1;
    int prefixIndex = -1;
    int suffixIndex = 0;

    while (suffixIndex < p.length - 1) {
        if (prefixIndex == -1 || p[prefixIndex] == p[suffixIndex]) {
            prefixIndex++;
            suffixIndex++;
            // 防止连续相同字符导致无效跳跃
            if (p[suffixIndex] == p[prefixIndex]) {
                next[suffixIndex] = next[prefixIndex];
            } else {
                next[suffixIndex] = prefixIndex;
            }
        } else {
            prefixIndex = next[prefixIndex];
        }
    }

    return next;
}

KMP 匹配函数实现

借助上述 next 数组,可编写完整的 KMP 匹配逻辑:

public static int kmpSearch(String text, String pattern) {
    char[] t = text.toCharArray();
    char[] p = pattern.toCharArray();
    int textIndex = 0;
    int patternIndex = 0;
    int[] next = buildNextArray(pattern);

    while (textIndex < t.length && patternIndex < p.length) {
        if (patternIndex == -1 || t[textIndex] == p[patternIndex]) {
            textIndex++;
            patternIndex++;
        } else {
            patternIndex = next[patternIndex];
        }
    }

    return patternIndex == p.length ? textIndex - patternIndex : -1;
}

相较于朴素匹配算法,KMP 最大的改进在于避免了文本指针的回退,使得时间复杂度降低至 O(n + m),其中 n 是文本长度,m 是模式串长度。

需要注意的一个优化点是:当模式串中存在连续相同的字符时,直接使用基础版 next 可能会导致不必要的比较。因此,在实际应用中推荐采用优化后的版本以提升效率。

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。