数据结构之KMP算法:彻底搞懂kmp算法

news2024/11/24 10:38:46

数据结构的学习,kmp匹配算法困扰我许久,此处来一个总结(仅供自己复习了解参考使用),如果有不对的地方请多多指点。好了废话不多说我们直接开始好吧。

目录

关于暴力匹配原理的讲解:

kmp算法:

数据前缀表next[j]和nextval[j]怎么写出来

 接下来我们来拿出来两个代码,第一个是暴力匹配代码,第二个是kmp匹配算法

暴力匹配的算法代码如下:

蛮力算法的时间复杂度 

KMP算法代码示例 

kmp算法的时间复杂度 

首先我想再次之前先讲述一下暴力匹配解法去匹配。

关于暴力匹配原理的讲解:

现在我们主串:“abcabaababab” 

模式串为:“abab”

我们现在来进行暴力匹配,开始匹配。

当匹配到第三个的时候,发现不对,就将“pat”中的第一位a与“txt”中第二位进行匹配,

 

 发现第一个就不匹配,那么我们继续进行匹配

还是第一个就没匹配成功,那么我们继续进行匹配 

我们发现第四位还是不匹配,那么我们继续一个一个的向下匹配,这里不多赘述,直到最后匹配成功 ,如果最后也没有匹配成功,那个则返回-1,没有得到匹配的结果。

kmp算法:

单匹配查找模式,一种字符串匹配的算法,它的效率是很高的,同时比较复杂,但是要是弄清楚它的原理后,其实它是挺简单的。接下来我们先从next数组入手。

关于kmp一定要知道前缀匹配表,这样才能了解清楚什么才是kmp匹配算法。kmp中的next数组就是一个前缀表。

那么我们提到的前缀表到底有什么用呢?

其实它可以帮助我们知道怎么匹配,前缀表是用来回退的,它记录了模式串与主串(文本串)不匹配的时候,模式串应该从哪里开始重新匹配。

还是以上面的例子

主串:“abcabaababab” 

模式串为:“abab”

我们来写模式串的next[j]和nextval[j],如下图

那么我们先来说一下他是如何进行匹配的(然后我们再说说这个表是怎么写出来的)

第一次匹配:在第三个位置出现了问题,那么我们进行第二次匹配

第二次匹配,我们进行查表,j=3的时候nextval是0,那么即0对应得是空,那么我们向前移一个 

 第三次匹配,j=1的时候还是没有匹配成功,那么我们还是向前移动一个位置

 第四次匹配:这次是j=4的时候不匹配,我们看表,j=4的时候nextval[4]=1,我们看那么我们将第一位也就是a移到i=7的位置。

 第五次匹配:

我们可以看到匹配成功,输出 

第六次匹配:

匹配成功后继续向下匹配

 第七次匹配:

查表后还是向下移动一位,匹配成功

 上述的过程就是进行匹配的过程,(这是本人的理解和学习,如有不同请多多指教)

数据前缀表next[j]和nextval[j]怎么写出来

我们先来讲解next[j]因为nextval[j]是按照next[j]来的。next的表格我们来写一下

我们先对串“abab”进行编号1-4。然后一般(我们是学习的严蔚敏的数据结构)我们将前两个标记为0和1,如下图所示 

 然后这里我们看第3位a,本身要不看要看它前两位的前缀和后缀

 前缀:a

后缀:b

找前缀和后缀的最大匹配项,在这里没有,所以为0,那么j=3的a的next为0+1 = 1。

 

 我们写出来它的网络前缀和后缀

前缀:a,ab

后缀:a,ba

这里我们看到有a与a这个最大匹配项,所以b的next值为 1 + 1=2

我们就写了它的next表格

 我们接下来写nextval的表格(要根据next表来写)

前两个数据还是0和1,如下图所示。

 我们来看第三个,第三a下面是1,我们去j=1对应的元素,如果是a,那么我们将a下面的nextval的值移到j=3的a下面,如果不是a,那么我们就将a下面next的值,移到nextval。

 我们来看第四个,同理,如果一致把2下面的nextval移过来,如果不一致,之间将b下面的2移到nextval那

 接下来我们来拿出来两个代码,第一个是暴力匹配代码,第二个是kmp匹配算法

暴力匹配的算法代码如下:

# Brute Force Algorithm
def brute_force_algorithm(string, pattern):
    n = len(string)
    m = len(pattern)
    for i in range(n-m+1):
        j = 0
        while j < m:
            if string[i+j] != pattern[j]:
                break
            j += 1
        if j == m:
            print("Pattern found at index " + str(i))

# Driver code to test above
string = "abcabaababab"
pattern = "abab"
brute_force_algorithm(string, pattern)

结果是两个值

蛮力算法的时间复杂度 

 我们来说一下它的时间复杂性

最糟糕的时间复杂性为,每一个都匹配一遍,即为每一个都匹配一遍

那么不难看出它的时间复杂性是O(n x n)。

KMP算法代码示例 

下面我们来看一下kmp算法,代码如下:

# KMP Algorithm
def kmp_algorithm(string, pattern):
    n = len(string)
    m = len(pattern)
    lps = [0] * m
    j = 0
    compute_lps_array(pattern, m, lps)
    i = 0
    while i < n:
        if pattern[j] == string[i]:
            i += 1
            j += 1
        if j == m:
            print("Found pattern at index " + str(i-j))
            j = lps[j-1]
        elif i < n and pattern[j] != string[i]:
            if j != 0:
                j = lps[j-1]
            else:
                i += 1

def compute_lps_array(pattern, m, lps):
    len = 0
    lps[0] = 0
    i = 1
    while i < m:
        if pattern[i] == pattern[len]:
            len += 1
            lps[i] = len
            i += 1
        else:
            if len != 0:
                len = lps[len-1]
            else:
                lps[i] = 0
                i += 1

# Driver code to test above
string = "abcabaababab"
pattern = "abab"
kmp_algorithm(string, pattern)

运行结果

kmp算法的时间复杂度 

 时间复杂度:假设M字符串中找N字符串的起始位置,长度分别是m和n,计算最长公共前缀后缀表长度的时候,比较的次数介于[m,2m]之间,比较模式串和子串时比较次数介于[n,2n]之间。所以时间复杂度为O(m+n)。

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

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

相关文章

ChatGPT - 如何高效的调教ChatGPT (指令建构模型-LACES问题模型)

文章目录 定义1. Limitation&#xff08;限定条件&#xff09;2. Assignment&#xff08;分配角色&#xff09;3. Context&#xff08;背景或上下文&#xff09;4. Example&#xff08;示例&#xff09;5. Step by Step&#xff08;拆分任务&#xff09; 小Demo 定义 LACES问题…

尚硅谷大数据技术Spark教程-笔记04【SparkCore(核心编程,RDD-行动算子-序列化-依赖关系-持久化-分区器-文件读取与保存)】

视频地址&#xff1a;尚硅谷大数据Spark教程从入门到精通_哔哩哔哩_bilibili 尚硅谷大数据技术Spark教程-笔记01【Spark&#xff08;概述、快速上手、运行环境、运行架构&#xff09;】尚硅谷大数据技术Spark教程-笔记02【SparkCore&#xff08;核心编程&#xff0c;RDD-核心属…

加强人工智能共性技术研发与产业化协同发展

央视网消息&#xff1a;“以5G为代表的新一代信息技术与制造业、交通、旅游等实体经济重要领域深度融合。”4月20日下午&#xff0c;国新办举行一季度工业和信息化发展情况新闻发布会&#xff0c;相关部门负责人在答问时表示&#xff0c;将用好融合应用这把金钥匙&#xff0c;开…

ReactHook学习(第一篇-N)

文章目录 Hook简介概述class组件的不足什么是 Hook?Hook 使用规则 state的研究&#xff08;useState&#xff09;State&#xff1a;组件的记忆&#xff08;响应式数据&#xff09;当普通的变量无法满足时添加一个 state 变量遇见你的第一个 Hook剖析 useState 赋予一个组件多个…

【C++】面向对象

文章目录 3.1 类与对象3.1.1 类成员的访问控制3.1.2 类的成员函数对象的访问方式成员函数的实现内联成员函数 3.1.3 构造函数复制构造函数调用复制构造函数的三种情况深复制与浅复制&#xff1f; 析构函数类的组合 3.1.4 前向引用声明3.1.5 结构体与类对比3.1.6 UML类图属性表示…

IMX6ULL裸机篇之按键消抖实验

一. 按键消抖 在之前的 按键中断实验时&#xff0c;我们讲了如何使用中断的方式驱动按键或GPIO。如果通过中断的方式处理按键的话&#xff0c;按键是需要消抖处理的。 而在之前 按键中断实验中&#xff0c;在中断处理函数中对按键进行消抖&#xff0c;调用了 delay 延时函数。…

剑指 Offer 32 - II. 从上到下打印二叉树 II

目录 题目思路BFS 题目来源 剑指 Offer 32 - II. 从上到下打印二叉树 II 题目思路 I. 按层打印&#xff1a; 题目要求的二叉树的 从上至下 打印&#xff08;即按层打印&#xff09;&#xff0c;又称为二叉树的 广度优先搜索&#xff08;BFS&#xff09;。BFS 通常借助 队列 的…

Midjourney v4 | 如何结合参考图像来生成AI艺术图

网址&#xff1a;midjourney.com 首页展示 首页如下图&#xff1a; 第一步&#xff1a;进入社群 点击首页右下角“Join the Beta”&#xff0c;进入如下页面&#xff1a; 点击“接受邀请”&#xff0c;验证之后进入 可以点击认证账号&#xff0c;进行注册&#xff1a; 应该不…

Redis三种集群模式

一、引言 Redis有三种集群模式&#xff0c;第一个就是主从模式&#xff0c;第二种“哨兵”模式&#xff0c;第三种是Cluster集群模式&#xff0c;第三种的集群模式是在Redis 3.x以后的版本才增加进来的&#xff0c;我们今天就来说一下Redis第一种集群模式&#xff1a;主从集群模…

【英语】100个句子记完7000个托福单词

其实主要的7000词其实是在主题归纳里面&#xff0c;不过过一遍100个句子也挺好的&#xff0c;反正也不多。 文章目录 Sentence 01Sentence 02Sentence 03Sentence 04Sentence 05Sentence 06Sentence 07Sentence 08Sentence 09Sentence 10Sentence 11Sentence 12Sentence 13Sent…

Redis的底层数据结构

Redis的底层数据结构 Redis的底层数据类型&#xff08;对比&#xff09;Redis的底层数据结构Redis数据类型和底层数据结构的对应关系Redis的使用 Redis的底层数据类型&#xff08;对比&#xff09; String&#xff08;字符串&#xff09;List&#xff08;列表&#xff09;Hash…

CRE66365 应用资料

CRE66365是一款高度集成的电流模式PWM控制IC&#xff0c;为高性能、低待机功耗和低成本的隔离型反激转换器。在正常负载条件下&#xff0c;AC输入高电压下工作在QR模式。为了最大限度地减少开关损耗&#xff0c;QR 模式下的最大开关频率被内部限制为 77kHz。当负载较低时&#…

Dcoekr 部署前后端分离项目SpringBoot +Vue

1.docker 部署vue docker 安装 nginx的镜像 niginx 配置文件 nginx.conf #user nobody; worker_processes 1;#error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info;#pid logs/nginx.pid;events {worker_connections…

给大家分享一个比Top更好用的Linux进程管理工具htop

一、前言 相信用过Linux操作系统的同学对Top应该都不陌生&#xff0c;我们通过Top命令可以查看CPU的占用率以及每个进程的详细信息&#xff0c;但是今天我要给大家分享一个比Top更好用的进程管理工具htop&#xff08;High Top&#xff09;。 二、htop功能介绍 htop 是一个高…

Shell编程规范及变量

这里写目录标题 一、Shell脚本编程概述1.1 shell脚本的概念1.2Shell脚本应用场景1.3 shell的作用1.4 linux中有哪些shell 二、 shell脚本的使用2.1shell脚本的构成2.2 运行脚本2.3 重定向和管道操作2.31交互式硬件设备2.32 重定向操作2.33 管道符号 三、shell脚本变量3.1 shell…

【FPGA-DSP】第九期:音频信号处理

从本文开始将记录一些简单的音频信号处理算法在System Generator中的实现方法。本文将介绍如何搭建音频信号的采集与输出模型。 音频信号属于一维信号&#xff0c;一些基本概念如下&#xff1a; 采样频率&#xff1a;根据奈奎斯特采样定理&#xff0c;采样频率Fs应该不低于声…

Vite vue 使用cdn引入element-plus

vite-plugin-cdn-import&#xff1a;cdn的引入插件 npm i vite-plugin-cdn-import or pnpm i vite-plugin-cdn-import vite.config.js import AutoImport from unplugin-auto-import/viteexport default defineConfig({ plugins: [vue({reactivityTransform: true}),importT…

0401概述-最短路径-加权有向图-数据结构和算法(Java)

文章目录 1 最短路径2 最短路径的性质3 加权有向图的数据结构3.1 加权有向边3.2 加权有向图 4 最短路径4.1 最短路径API4.2 最短路径的数据结构4.3 边的松弛4.4 顶点的松弛 结语 1 最短路径 如图1-1所示&#xff0c;一幅加权有向图和其中的一条最短路径&#xff1a; 定义&…

事务—MySQL

文章目录 1.事务的四大特性1.1原子性1.2一致性1.3隔离性1.4持久性 2.并发访问中存在的一些问题2.1丢失更新2.2脏读2.3不可重复读2.4幻读 3.隔离级别解决一致性的问题3.1未提交读3.2提交读3.3可重复读3.4可串行化 4.不同隔离级别可以解决的问题 1.事务的四大特性 1.1原子性 事…

BBR原版/魔改/plus/锐速/七合一脚本linux加速脚本/硬盘挂载/cc防御/宝塔

BBR原版/魔改/plus/锐速七合一脚本linux加速脚本/硬盘挂载/CC防御/宝塔 新云分享的七合一脚本&#xff0c;包含原版BBR、魔改BBR、bbrplus以及锐速可选。 在vultr上Centos 7, Debian 8/9, Ubuntu 16/18测试通过&#xff0c;不支持ovz。 安装指令&#xff1a;复制下面命令在s…