当前位置: 首页 > news >正文

KMP算法!

KMP算法(Knuth-Morris-Pratt算法)是一种用于字符串匹配的高效算法。它的核心思想是通过预处理模式字符串(pattern),构建一个部分匹配表(也称为“失败函数”或“前缀函数”),从而在匹配过程中避免不必要的回溯。KMP算法的时间复杂度为O(n + m),其中n是文本字符串的长度,m是模式字符串的长度。

KMP算法的核心思想

  1. 部分匹配表(Prefix Table)

    • 部分匹配表记录了模式字符串中每个位置的最长相同前缀和后缀的长度。

    • 例如,对于模式字符串"ABABC",其部分匹配表为[0, 0, 1, 2, 0]

  2. 匹配过程

    • 在匹配过程中,当字符不匹配时,KMP算法利用部分匹配表跳过一些字符,避免从头开始匹配。

KMP算法的步骤

  1. 构建部分匹配表

    • 初始化一个数组prefix,长度为模式字符串的长度。

    • 使用两个指针,一个指向模式字符串的开头(i),另一个用于遍历模式字符串(j)。

    • 如果字符匹配,prefix[j] = i + 1,并移动两个指针。

    • 如果不匹配,且i > 0,则将i回退到prefix[i - 1]

    • 如果不匹配,且i == 0,则prefix[j] = 0,并移动j

  2. 匹配文本字符串

    • 使用两个指针,一个指向文本字符串(i),另一个指向模式字符串(j)。

    • 如果字符匹配,移动两个指针。

    • 如果不匹配,且j > 0,则将j回退到prefix[j - 1]

    • 如果不匹配,且j == 0,则移动i

public class KMP {

    // 计算部分匹配表(前缀函数)
    private static int[] computePrefix(String pattern) {
        int[] prefix = new int[pattern.length()];
        int j = 0; // 指向模式字符串的前缀
        for (int i = 1; i < pattern.length(); i++) {
            while (j > 0 && pattern.charAt(i) != pattern.charAt(j)) {
                j = prefix[j - 1]; // 回退到前一个匹配位置
            }
            if (pattern.charAt(i) == pattern.charAt(j)) {
                j++; // 匹配成功,移动 j
            }
            prefix[i] = j; // 记录当前位置的最长前缀
        }
        return prefix;
    }

    // KMP 搜索算法
    public static int kmpSearch(String text, String pattern) {
        int[] prefix = computePrefix(pattern);
        int j = 0; // 指向模式字符串
        for (int i = 0; i < text.length(); i++) {
            while (j > 0 && text.charAt(i) != pattern.charAt(j)) {
                j = prefix[j - 1]; // 回退到前一个匹配位置
            }
            if (text.charAt(i) == pattern.charAt(j)) {
                j++; // 匹配成功,移动 j
            }
            if (j == pattern.length()) {
                return i - j + 1; // 返回匹配的起始位置
            }
        }
        return -1; // 未找到匹配
    }

    public static void main(String[] args) {
        String text = "ABABDABACDABABCABAB";
        String pattern = "ABABCABAB";
        int index = kmpSearch(text, pattern);
        if (index != -1) {
            System.out.println("Pattern found at index: " + index);
        } else {
            System.out.println("Pattern not found.");
        }
    }
}

示例输出

对于文本字符串 "ABABDABACDABABCABAB" 和模式字符串 "ABABCABAB",输出结果为:

Pattern found at index: 10

 

优点

  • 高效:KMP算法避免了不必要的回溯,提高了匹配效率。

  • 适用性广:适用于各种字符串匹配场景,尤其是模式字符串较长的情况。

缺点

  • 实现复杂:相比暴力匹配算法,KMP算法的实现较为复杂。

  • 空间开销:需要额外的空间存储部分匹配表。

KMP算法是字符串匹配领域的重要算法,理解其原理和实现对于解决相关问题非常有帮助。

相关文章:

  • Linux 基础---sudo权限 修改文件所属人、用户所属组
  • 【论文阅读笔记】用于恶劣天气条件下的目标检测的IA-YOLO(Image-Adaptive YOLO) | 适合雾天和低光照场景
  • 爱吃蟠桃的孙悟空
  • Deepseek API+Python测试用例一键生成与导出
  • JavaWeb(Day8)-登录校验(JWT令牌,Filter过滤器,Interceptor拦截器)
  • MySQL零基础教程14—子查询
  • Mybatis 的代理开发方式
  • golang接口
  • JS逆向获取算法 使用算法逻辑进行爆破
  • 晨控CK-FR03与汇川H5U系列PLC配置EtherCAT通讯连接手册
  • 蓝桥杯真题解题思路——因数计数
  • [免费]微信小程序(校园)二手交易系统(uni-app+SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】
  • C++小课堂——构造函数与析构函数
  • 2025 Lakehouse 趋势全景展望:从技术演进到商业重构
  • Linux线程
  • Tauri+React+Ant Design跨平台开发环境搭建指南
  • Maven
  • B3DM转换成PLY
  • Spark之数据倾斜调优
  • 【后端】Flask vs Django vs Node.js 对比分析
  • 印巴开始互袭军事目标,专家:冲突“螺旋式升级”后果或不可控
  • 央行谈MLF:逐步退出政策利率属性回归流动性投放工具
  • 习近平向中国人民解放军仪仗队致意
  • 复旦发文缅怀文科杰出教授裘锡圭:曾提出治学需具备三种精神
  • 中华人民共和国和俄罗斯联邦关于进一步加强合作维护国际法权威的联合声明
  • 融创中国:今年前4个月销售额约112亿元