字符串算法之KMP 算法(Knuth-Morris-Pratt Algorithm, 字符串匹配)详细解读

ops/2024/10/19 22:06:09/

KMP算法(Knuth-Morris-Pratt Algorithm) 是一种高效的字符串匹配算法,用于在一个文本串中查找一个模式串的位置。它通过预处理模式串,减少了不必要的比较次数,从而提高了匹配效率。KMP算法的时间复杂度为 O(n+m),其中 n 是文本串的长度,m 是模式串的长度。

KMP算法的基本原理

KMP算法的核心思想是使用已匹配的部分信息来避免重复比较。在匹配过程中,如果出现不匹配,KMP算法不会重新从头开始比较,而是利用一个部分匹配表(或称为“前缀表”)来决定从哪个位置重新开始匹配。

部分匹配表(前缀表)

部分匹配表(pi数组)是一个数组,其中的每个元素 pi[i] 表示模式串中,前 i 个字符的最长相等前后缀的长度。这个表的作用是在出现不匹配时,帮助我们跳过已匹配的部分,直接从合适的位置继续比较。

例如,对于模式串 "ABABCABAB",其前缀表如下:

  • A:前缀 "",后缀 "",长度为 0。
  • AB:前缀 "A",后缀 "",长度为 0。
  • ABA:前缀 "A",后缀 "A",长度为 1。
  • ABAB:前缀 "AB",后缀 "AB",长度为 2。
  • ABABC:前缀 "ABAB",后缀 "A",长度为 0。
  • ABABCA:前缀 "ABABC",后缀 "AB",长度为 2。
  • ABABCAB:前缀 "ABABCA",后缀 "ABAB",长度为 3。
  • ABABCABA:前缀 "ABABCAB",后缀 "AB",长度为 2。
  • ABABCABAB:前缀 "ABABCABA",后缀 "ABAB",长度为 4。

对应的前缀表为:

pi = [0, 0, 1, 2, 0, 1, 2, 3, 4]

KMP算法的步骤

  1. 构建部分匹配表:根据模式串生成前缀表 pi
  2. 匹配过程
    • 使用两个指针 ij,分别指向文本串和模式串的当前字符。
    • text[i] == pattern[j] 时,两个指针同时向后移动。
    • 如果 j 达到模式串的长度,说明找到了匹配,记录匹配位置。
    • 如果不匹配:
      • 如果 j > 0,则根据 pi[j - 1] 更新 j,即跳过已匹配的部分。
      • 如果 j == 0,则只移动 i

KMP算法的Java实现

以下是 KMP算法的 Java 实现示例:

public class KMPAlgorithm {// 构建部分匹配表private int[] buildPrefixTable(String pattern) {int[] pi = 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 = pi[j - 1]; // 回退到上一个最长相等前后缀}if (pattern.charAt(i) == pattern.charAt(j)) {j++; // 找到匹配,增加前缀长度}pi[i] = j; // 更新前缀表}return pi;}// KMP匹配算法public void KMP(String text, String pattern) {int[] pi = buildPrefixTable(pattern); // 构建部分匹配表int j = 0; // 模式串的指针for (int i = 0; i < text.length(); i++) {while (j > 0 && text.charAt(i) != pattern.charAt(j)) {j = pi[j - 1]; // 回退到上一个最长相等前后缀}if (text.charAt(i) == pattern.charAt(j)) {j++; // 找到匹配}if (j == pattern.length()) {System.out.println("Pattern found at index: " + (i - j + 1));j = pi[j - 1]; // 继续寻找下一个匹配}}}public static void main(String[] args) {KMPAlgorithm kmp = new KMPAlgorithm();String text = "ABABDABACDABABCABAB";String pattern = "ABABCABAB";kmp.KMP(text, pattern); // 在文本中查找模式串}
}

代码解读

  1. buildPrefixTable 方法:构建模式串的前缀表 pi,用于记录模式串中每个字符的最长相等前后缀的长度。

    • j 表示当前前缀的长度,循环遍历模式串,更新前缀表。
    • 在字符不匹配时,通过 pi 数组回退 j,找到合适的前缀长度。
  2. KMP 方法:实现 KMP 字符串匹配算法

    • 使用两个指针 ij,分别遍历文本串和模式串。
    • 当字符匹配时,两个指针向后移动,若 j 达到模式串长度,说明找到了匹配。
    • 输出匹配的位置,并根据 pi 数组更新 j,继续查找其他匹配。
  3. main 方法:创建 KMPAlgorithm 实例,并在给定的文本串中查找指定的模式串。

KMP算法的优缺点

优点
  • 时间复杂度低:KMP算法的时间复杂度为 O(n+m),效率高于简单的暴力匹配算法
  • 避免重复比较:通过部分匹配表,可以避免对已匹配部分的重复比较。
缺点
  • 实现复杂:相比简单的暴力匹配,KMP算法的实现较为复杂,需要理解前缀表的构建。
  • 空间复杂度:需要额外的空间来存储前缀表,空间复杂度为 O(m)。

应用场景

  • KMP算法在文本搜索、DNA序列比对、编译器词法分析等领域具有广泛的应用。其高效的匹配能力使其成为字符串匹配问题中的重要选择。

http://www.ppmy.cn/ops/126815.html

相关文章

极客wordpress模板

这是一个展示WordPress主题的网页设计。页面顶部有一个导航栏&#xff0c;包含多个选项&#xff0c;如“关于我们”、“产品中心”、“案例展示”、“新闻动态”、“联系我们”和“技术支持”。页面中间部分展示了多个产品&#xff0c;每个产品都有一个图片和简短的描述。页面下…

OpenCV物体跟踪:使用CSRT算法实现实时跟踪

目录 简介 CSRT算法简介 实现步骤 1. 初始化摄像头和跟踪器 2. 读取视频帧和初始化跟踪 3. 实时跟踪和显示结果 4. 显示和退出 5、结果展示 总结 简介 在计算机视觉和视频处理领域&#xff0c;物体跟踪是一项核心技术&#xff0c;它在监控、人机交互、运动分析等方面…

基于SSM+微信小程序的实验室设备故障报修管理系统2

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1、项目介绍 基于SSM微信小程序的实验室设备故障报修管理系统2实现了管理员&#xff0c;用户&#xff0c;维修员三个角色。 管理员功能有 个人中心&#xff0c;用户管理&#xff0c;维修员管理&#…

Kamailio-Sngrep 短小精悍的利器

一个sip的抓包小工具&#xff0c;在GitHub上竟然能够积累1K的star&#xff0c;看来还是有点东西&#xff0c;当然官方的友链也是发挥了重要作用 首先送上项目地址&#xff0c;有能力的宝子可以自行查看 经典的网络抓包工具有很多&#xff0c;比如&#xff1a; Wireshark&…

Java前后端交互:构建现代Web应用

在现代Web应用开发中&#xff0c;前后端分离是一种常见的架构模式。后端通常负责数据处理和业务逻辑&#xff0c;而前端则负责用户界面和用户体验。Java作为后端开发的强大语言&#xff0c;提供了多种方式与前端进行交互。本文将探讨Java后端与前端交互的几种主要方式&#xff…

性能评测第一,阿里开源可商用AI模型Ovis 1.6使用指南,AI多模态大模型首选

什么是 Ovis 1.6 Gemma 2 9B&#xff1f; Ovis 1.6 Gemma 2 9B 是阿里国际AI团队推出的最新多模态大模型&#xff08;Multimodal Large Language Model&#xff0c;MLLM&#xff09;。该模型旨在结构化地对齐视觉和文本嵌入&#xff0c;能够处理和理解多种不同类型的数据输入&…

面试应该问什么?

在求职者面试的过程中&#xff0c;向面试官提问是一个展现自己积极态度、对职位和公司兴趣以及进一步了解工作环境和职业发展机会的重要环节。以下是一些求职者可以在面试中向面试官提问的问题&#xff0c;这些问题旨在帮助你更全面地了解未来的工作环境、团队文化、以及个人职…

VScode实现服务器免密登录(亲测有效)

目录 1 免密步骤1.1 在本地生成密钥1.2 在vscode中下载Remote-SSH1.3 配置SSH文件1.4 在服务器中添加本地公开密钥1.5 远程免密连接试验 2 后记 1 免密步骤 1.1 在本地生成密钥 window R打开命令面板 ssh-keygen1.2 在vscode中下载Remote-SSH 1.3 配置SSH文件 本地密钥的文…