字符串匹配——KMP算法

news2025/2/23 2:30:36

目录

KMP(Knuth Morris Pratt)

KMP算法复杂度分析

字符串匹配中除了简单的BF(Brute Force)、RK(Rabin-Karp)算法,还有更高效、较难理解的

BM(Boyer-Moore)和KMP(Knuth Morris Pratt)算法。这次来聊聊KMP(Knuth Morris Pratt)算法。

KMP(Knuth Morris Pratt)

KMP算法是根据三位作者(D.E.Knuth,J.H.Morris和V.R.Pratt)的名字来命名的,算法的全称是Knuth Morris Pratt算法,简称为KMP算法。

KMP算法的核心思想和BM(Boyer-Moore)非常相近。(BM算法简介)

为了表述起来方便,好前缀的所有后缀子串中,最长的可匹配前缀子串的那个后缀子串,叫作最长可匹配后缀子串;对应的前缀子串,叫作最长可匹配前缀子串。

需要提前构建一个数组,用来存储模式串中每个前缀(这些前缀都有可能是好前缀)的最长可匹配前缀子串的结尾字符下标,叫做next数组。

数组下标是每个前缀的结尾字符下标,数组值是这个前缀的最长可匹配前缀子串的结尾字符下标。

模式串:a b a b a b e a b

模式串前缀 (好前缀候选情况枚举)模式串前缀 结尾字符下标最长匹配前缀子串最长匹配后缀子串最长匹配前缀子串 结尾字符下标next值
a0无子串无子串-1(表示不存在)netx[0]=-1
ab1ab-1netx[1]=-1
aba2aa0netx[2]=0
abab3abab1netx[3]=1
ababa4abaaba2netx[4]=2
ababab5abababab3netx[5]=3
abababe6无符合子串无符合子串-1netx[6]=-1
abababea7aa0netx[7]=0
abababeab8abab1netx[8]=1

在next数组的帮助下,KMP算法就方便实现了。假设next数组已计算好,KMP的算法框架大致如下:

// a和b表示主串和模式串,n和m分表表示主串和模式串的长度
public static int kmp(char[] a, int n, char[] b, int m) {
    int[] next = getNextArr[b, m];// 通过模式串获取next数组
    int j = 0;
    for(int i = 0; i < n; i++) {
        while(j > 0 && a[i] != b[j]) { // 一直找到a[i] = b[j]
            j= next[j - 1] + 1; 
        }
        if (a[i] == b[j]) { 
            ++j;
        }
        if (j == m) { // 找到匹配的串了
            return i - m + 1;
        }
    }
    return -1;
}

接下来需要解决的是getNextArr了。

我们按照下标从小到大,依次计算next数组的值。当我们要计算next[i]的时候,前面的next[0],next[1],……,next[i-1]应该已经计算出来了。 如果next[i-1]=k-1,也就是说,子串b[0, k-1]是b[0, i-1]的最长可匹配前缀子串。如果子串b[0, k-1]的下一个字符b[k],与b[0, i-1]的下一个字符b[i]匹配,那子串b[0, k]就是b[0, i]的最长可匹配前缀子串。所以,next[i]等于k。但是,如果b[0, k-1]的下一字符b[k]跟b[0, i-1]的下一个字符b[i]不相等呢?这个时候就不能简单地通 过next[i-1]得到next[i]了。

我们假设b[0, i]的最长可匹配后缀子串是b[r, i]。如果我们把最后一个字符去掉,那b[r, i-1]肯定是b[0, i-1]的可匹配后缀子串,但不一定是最长可匹配后缀子串。所 以,既然b[0, i-1]最长可匹配后缀子串对应的模式串的前缀子串的下一个字符并不等于b[i],那么我们就可以考察b[0, i-1]的次长可匹配后缀子串b[x, i-1]对应的可匹配前缀子串b[0, i-1-x]的下一个字符b[i-x]是否等于b[i]。如果等于,那b[x, i]就是b[0, i]的最长可匹配后缀子串。

次长可匹配后缀子串肯定被包含在最长可匹配后缀子串中,而最长可匹配后缀子串又对应最长可匹配前缀子串b[0, y]。于是,查找b[0, i-1]的次长可匹配后缀子串,这个问题就变成,查找b[0, y]的最长匹配后缀子串的问题了。

按照这个思路,我们可以考察完所有的b[0, i-1]的可匹配后缀子串b[y, i-1],直到找到一个可匹配的后缀子串,它对应的前缀子串的下一个字符等于b[i],那这个b[y, i]就是b[0, i]的最长可匹配后缀子串。

// b表示模式串,m表示模式串的长度
private static int[] getNexts(char[] b, int m) {
    int[] next = new int[m];
    next[0] = -1;
    int k = -1;
    for (int i = 1; i < m; ++i) {
        while (k != -1 && b[k + 1] != b[i]) {
            k = next[k];
        }
        if (b[k + 1] == b[i]) {
            ++k;
        }
        next[i] = k;
    }
    return next;
}
KMP算法复杂度分析

KMP算法包含两部分,第一部分是构建next数组,时间复杂度主要取决于while循环里面k=next[k]总的执行次数,这部分时间复杂度是O(m)。第二部分才是借助next数组匹配,取决于while循环中的这条语句总的执行次数也不会超过n,所以这部分的时间复杂度是O(n)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1088320.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android之根据时区获取当前时间

文章目录 前言偶尔我们也会做多个国家的APP&#xff0c;难免少不了时间显示&#xff0c;所以我们就需要获取当前时区的当前时间&#xff0c;几句代码解决、 一、效果图二、实现步骤1.TimeUtil2.调用 总结 前言 偶尔我们也会做多个国家的APP&#xff0c;难免少不了时间显示&…

从公司搭建的gitlab代码仓拉取代码失败问题

从gitlab代码仓拉取代码失败问题解决 1.问题描述2.分析解决3.解决问题 1.问题描述 1.在访问到从公司搭建的gitlab代码仓后&#xff0c;选择了要拉取的地址&#xff0c;使用git拉取代码时&#xff0c;拉取失败&#xff0c;报错如下 2.分析解决 1.因为网页可以看到代码仓中这…

yolov7模型训练环境安装

ANACONDA Free Download | Anacondahttps://www.anaconda.com/download/进入ANACONDA安装的盘后输入python测试环境是否安装完成 进入 cd Scripts后 在同路径下下载&#xff0c;pip install opencv-python cd.. 退回上层 python 打开’ import cv2 cv2.__version__…

Redis学习1

NOSql型数据库 NoSQL&#xff08;Not Only SQL&#xff09;是一种数据库管理系统的范畴&#xff0c;它不使用传统的关系型数据库管理系统&#xff08;RDBMS&#xff09;模型。相对于传统的关系型数据库&#xff0c;NoSQL 数据库在数据存储和检索方面提供了更多的灵活性和可伸缩…

B端企业为什么需要软文推广?媒介盒子告诉你

在传统的营销概念中&#xff0c;大部分人认为B端企业不需要品牌曝光&#xff0c;企业只需要靠质量与服务就能获得稳定客源&#xff0c;而在互联网加速发展的今天&#xff0c;B端企业的营销方式也发生变化&#xff0c;有不少B端企业来找媒介盒子进行软文推广&#xff0c;接下来媒…

Git遇到问题收集

您的企业已过期或者超过配额&#xff0c;请升级或续订&#xff01; 如何解决&#xff1a; 此问题是企业仓库满额导致&#xff0c;联系公司的gitee管理人员进行处理

c++图像处理-----自适应阈值操作:`cv::adaptiveThreshold()`

自适应阈值操作&#xff1a;cv::adaptiveThreshold() cv::adaptiveThreshold()是OpenCV库中的一个函数&#xff0c;用于图像处理中的自适应阈值二值化操作。这个函数通常用于将灰度图像转换为二值图像&#xff0c;其中每个像素的阈值是根据其周围邻域的像素值自动确定的&#…

(2023|CVPR,中文,扩散,知识增强,去噪专家组合)ERNIE-ViLG 2.0:利用知识增强的去噪专家组合改进文本到图像扩散模型

ERNIE-ViLG 2.0: Improving Text-to-Image Diffusion Model with Knowledge-Enhanced Mixture-of-Denoising-Experts 公众号&#xff1a;EDPJ&#xff08;添加 VX&#xff1a;CV_EDPJ 或直接进 Q 交流群&#xff1a;922230617 获取资料&#xff09; 目录 0. 摘要 1. 简介 …

Windows 进程监视工具

Windows 进程监视器是一种工具&#xff0c;可帮助 IT 管理员监视其 Windows IT 基础结构终结点中的关键进程&#xff0c;并确保其持续可用性、一致的运行状况和最佳性能。通过主动监视关键服务&#xff0c;Windows 进程监视器可帮助 IT 管理员确保其 Windows 进程不会意外关闭或…

纯 CSS 实现瀑布流布局的方法

纯 CSS 实现瀑布流布局的方法 这种方式兼容性不是很好&#xff0c;全部支持需要些时间&#xff0c;但是目前是可以使用 css 写出来的 display: grid; grid-template-columns: repeat(4, 1fr); grid-gap: 10px; grid-template-rows: masonry;全部的 css .container {display:…

C语言中的文件操作函数

C语言中的文件操作函数_c语言文件操作函数_点子李的博客-CSDN博客C语言文件操作_c语言文件操作函数https://blog.csdn.net/qq_53332052/article/details/128470575?utm_mediumdistribute.pc_relevant.none-task-blog-2~default~baidujs_utm_term~default-1-128470575-blog-125…

【ROS】ros-noetic和anaconda联合使用(1)

【ROS】ros-noetic和anaconda联合使用&#xff08;1&#xff09; 文章目录 【ROS】ros-noetic和anaconda联合使用&#xff08;1&#xff09;1. 安装anaconda2. 创建虚拟环境3. 查看python解释器路径4. 在虚拟环境中使用任意的包5. 创建工作空间和ros功能包进行测试Reference 1.…

Liunx系统管理的引导过程与服务控制

引导过程&#xff1a; liunx系统的开机过程&#xff1a; 开机自检(BIOS):linux主机开机之后&#xff0c;根据主板BIOS中的设备&#xff0c;对CPU内存 显卡 键盘等等设备进行初步检测 检测成功之后&#xff0c;根据预设的启动柜顺序进行系统控制权的移交 一般情况下&#xf…

阿里云云安全中心详细介绍(原态势感知)功能价格说明

阿里云云安全中心&#xff08;原态势感知&#xff09;是一个实时识别、分析、预警安全威胁的服务器主机安全管理系统&#xff0c;云安全中心功能支持漏洞扫描与修复、基线检查、防勒索、防病毒、防篡改、威胁检测模型等功能&#xff0c;云安全中心基础版免费、防病毒班432元一年…

网络安全—小白学习笔记

1.网络安全是什么 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 2.网络安全市场 一、是市场需求量高&#xff1b; 二、则是发展相对成熟入…

水库大坝安全监测是什么和主要作用?

水库大坝安全监测是指通过仪器观测和巡视检查对水利水电工程主体结构、地基基础、两岸边坡、相关设施以及周围环境所作的测量及观察。大坝安全监测是作为水库大坝安全管理的重要组成部分&#xff0c;是掌握水库大坝安全性态的重要手段&#xff0c;是科学调度、安全运行的前提。…

Java进阶 之 再论面向对象(3)——构造方法Constructors 以及 调用的分析 JavaBean的概念 构造函数中this关键字

前言 在前面博客中&#xff0c;我们从面向过程和面向对象的编程思想谈起&#xff0c;阐述了类和对象在Java中的编程中的应用&#xff0c;此外&#xff0c;对于对象的内存&#xff0c;变量作用域&#xff0c;参数传递等进行了阐述。 Java进阶 之 再论面向对象&#xff08;1&am…

配电房监测系统:智能化电力管理的关键

随着社会的发展和科技的进步&#xff0c;电力设施的重要性日益凸显。其中&#xff0c;配电房作为电能分配的核心设施&#xff0c;其运行状态直接影响到电力系统的稳定性和可靠性。为了确保配电房的高效运行&#xff0c;采用配电房监测系统成为关键。此类系统利用先进的智能电力…

企业数字化转型的必选项:集成自动化

NO.1 将“不可能”变成“可能”的自动化工作流 在智能化时代&#xff0c;我们经常会听到“工作流”这个词&#xff0c;但很多人并不清晰它真正的含义&#xff0c;简单来说&#xff0c;它是一个与其他场景流程集成的应用程序&#xff0c;目标是自动化各应用之间的流程&#xf…

【ivX】低调且强大的低代码平台

目录 前言 一、低代码那么多 为什么选择iVX&#xff1f; 二、“拼”出来的低代码平台&#xff0c;真的好用吗&#xff1f; 前言 首先我们应该明白自动编程突破可能是&#xff1a;领域内Mini LLM 现在的思路都是搞LLM&#xff0c;几乎像“大跃进”一样全民都在修炼“大模型”…