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

【第十二课】KMP算法(acwing-831 / c++代码 / 思路 / 视频+博客讲解推荐)

目录

暴力做法

代码如下 

KMP算法

不同的next求法-----视频讲解/博客推荐

视频推荐

博客推荐

课本上的方法-

prefix的方法-

求next数组思路---next数组存放前缀表的方式

s和p匹配思路

代码如下


暴力做法

遍历s主串中每一个元素如果该元素等于模板串p中的第一个元素,就进入内层遍历模板串p中的每一个字符,看该元素及其后面几个元素是否都与模式串p完全一致。避免起初 i 下标丢失,需要定义几个变量,代替 i 作为下标索引。如果发现有不同的,说明这个起始元素并不是我们想要的答案,执行内层循环的if语句,start是我们判断的标记,如果执行了if语句start赋值为-1,说明不必将原本的start放进答案数组

由此得出答案。

需要注意定义ans答案数组为vector动态数组,其添加元素直接调用push_back()函数。(问就是我刚开始写错了[点手指]...)

代码如下 

#include<iostream>
#include<vector>
using namespace std;
int main()
{int n,m;string p,s;cin>>n;cin>>p;//模板串  子串cin>>m;cin>>s;//模式串  主串int k=0;int start=-1;vector<int> ans;int v=0;for(int i=0;i<m;i++){if(s[i]==p[0]){start=i;k=start;for(int j=0;j<n;j++,k++){if(s[k]!=p[j]){k=0;start=-1;break;}}if(start!=-1)ans.push_back(start);}}for(int i=0;i<ans.size();i++){cout<<ans[i]<<" ";}return 0;
}

KMP算法

就像是在归并排序过程中顺便计算出了逆序对一样,我们在暴力做法里,每次匹配的过程中也做了一些后期优化能够利用上的过程

kmp算法思想:用来求解模式串匹配的相关问题。每次我们s主串数组和p模式串数组进行匹配的过程中,已经有一部分是匹配的,而发现下一个元素不匹配,此时我们如果存在next数组记录着p模式串中每个元素之前的前缀和后缀的最长相等的长度,就可以让p数组移动到与其后缀对齐的位置,继续向下比较  (这个"移动"是通过更新索引j来改变我们接下来要比较的元素,而不是实际改变模式串p的位置),从而提高了效率.

不同的next求法-----视频讲解/博客推荐

在写完这个思路之后,我发现这里我们这种方法求得的next数组其实和课本上,如下图

这种方法所得的结果是不一致的。

视频推荐

b站这个姐姐按课本上的计算方法讲的很清晰,放在这里啦,放心食用~(提一下这个姐姐也讲了数据结构重点知识的速成课,讲的也很不错,最近要期末考的[我]可以看看~)

http:www.bilibili.com/video/BV1PG4y1V7Zq?vd_source=02dfd57080e8f31bc9c4a323c13dd49c

其实这种next数组的求法是 我们这里使用的前缀表得出的next数组统一向右移一位,第一位补-1,再同时给每个数+1所得到的。(我把我们使用得前缀表的方法用prefix来表示)

下面这个视频中有一些动态的匹配过程,可以看看帮助理解一下思路~ 

http:www.bilibili.com/video/BV1jb411V78H?vd_source=02dfd57080e8f31bc9c4a323c13dd49c 

这里我真困惑了好一阵,又看了很多其他的视频讲解,下面是b站代码随想录老师按照我们这里next数组存前缀表的理论方法讲解的很详细👇可以多看几遍

http:www.bilibili.com/video/BV1PD4y1o7nd?vd_source=02dfd57080e8f31bc9c4a323c13dd49c

同时老师也出了专门讲代码的视频,那个视频前5分钟讲的是next的不同实现方法,解决了我关于这方面的疑惑,可以看一下哦~

博客推荐

也看了一些博客,不过感觉视频讲解更清楚明了一些,视频讲解优先~(这些博客我没有完整的看完[比较长] 只是一股优质好文的味道)

课本上的方法-

这个是给出了动态图片,比较好理解

http://blog.csdn.net/qq_37969433/article/details/82947411

这个是对课本上next数组的定义进行了详细的阐释 

http://blog.csdn.net/weixin_46307478/article/details/124589160

prefix的方法-

这两篇是和本篇我写的方法一致,感觉讲的更清晰一些[惭愧] 一起学习

http://blog.csdn.net/qq_52127701/article/details/126057058

http://zhuanlan.zhihu.com/p/576363046?utm_id=0

这个对跳转的过程(即j指针的移动)展示的比较清晰

http://blog.csdn.net/weixin_43972154/article/details/121357012

这个是详细解释了优化的地方

http://blog.csdn.net/oceanriverguo/article/details/129644605

求next数组思路---next数组存放前缀表的方式

  

我们手算的方法就像图里这样。下面是对应代码,感觉不太好理解。 

for(int i=2,j=0;i<=n;i++){while(j && p[i]!=p[j+1])j=ne[j];if(p[i]==p[j+1])j++;ne[i]=j;}

对于模式串p的每一个位置 i,我们都试图找出其最长的相等前后缀的长度,也就是ne[i],即ne[i] 表示模式串 p 的前缀 p[1,i ] 的最长相等前缀和后缀的长度

 i 表示当前正在考虑的模式串字符的位置。遍历p数组每一个元素,找出其对应的ne[j]

 j 表示当前已匹配过的模式串的最长前缀和后缀相等的长度.默认是前缀 j 个元素。

如果p[i] (模式串的第 i 个字符)与前缀的下一个字符 p[ j+1] 相等,我们增加 j 的值,表示找到了更长的相等前缀和后缀

while循环的作用:通过不断缩短 j 的值,寻找当前位置 i 对应的字符的最长前缀和后缀相等的长度

我们需要执行 while 循环,因为在 p[i] != p[j+1] 的情况下,我们希望继续缩短 j,直到找到满足 p[i] == p[j+1] 的 j。通过这个过程,我们能够确保在当前位置 i 找到的 j 是满足条件的最大值。 

while循环条件: j && p[i]!=p[j+1] ,当 j 为零时,表示当前没有已匹配的前缀和后缀相等的部分,就不需要缩短j 。如果当前i所对元素与p[j+1]元素不等,说明不匹配。当发现不匹配时,我们希望缩短 j。ne[j] 存储了当前前缀 p[1..j] 的最长相等前缀和后缀的长度。所以,j = ne[j] 实际上将 j 缩短到前缀的最长相等前缀和后缀的长度,以便继续尝试寻找更短的相等部分。举例:

abcaabb 对应 Next数组:0 0 0 1 1 2 0

abcabcd 对应 Next数组:0 0 0 1 2 3 0

aabbacddc 对应 Next数组: 0 1 0 0 1 0 0 0 0

if(p[i] == p[j+1]) j++; 是在找到相等部分时增加 j 的值。且这个 j 的值在下一轮循环中会利用之前得到的 j。所以比如下面这个:我找第一个a的时候是0 第二个b也是0 ,第三个p[3]=p[1] 得到j=1;第四个,这是j已经不是等于1了,我们判断p[i]与p[j+1]的关系,这里是相等的,执行了该if语句,j++,此时j=2了。后面我只要看p[i]与p[j+1]相等的话我直接j+1,不等的话就和前面的数的ne[j]一致。这样计算很快了。

s和p匹配思路

 上面next数组思路明白之后,这个匹配的过程思路是差不多了。

if(j==n){printf("%d ",i-n);j=ne[j];}

 这里我们遍历完之后,还是将j移动到ne[j]的位置,继续进行下一轮的匹配。

代码如下

#include<iostream>
using namespace std;
const int N=1e5+10,M=1e6+10;
int n,m;
char p[N],s[M];
int ne[N];//ne[1]=0
int main()
{cin>>n>>p+1>>m>>s+1;//因为我们希望从1开始存储元素,而默认下标从0开始 所以要+1//计算ne数组for(int i=2,j=0;i<=n;i++)//ne[1]=0{while(j && p[i]!=p[j+1])j=ne[j];if(p[i]==p[j+1])j++;ne[i]=j;}for(int i=1,j=0;i<=m;i++){while(j && s[i]!=p[j+1])j=ne[j];if(s[i]==p[j+1])j++;if(j==n){printf("%d ",i-n);//本来是i-n+1,但这里题目要求我们下标从0开始j=ne[j];}}return 0;
}

kmp拖了好久了,感觉不太好理解,,, ,,写的不好,一些细节没有讲到(但推荐的文章里对这些部分讲的很清楚),懒了qaq,这几天状态不好。。。。

如果有问题欢迎指出,非常感谢!!

也欢迎交流和建议哦!

相关文章:

【第十二课】KMP算法(acwing-831 / c++代码 / 思路 / 视频+博客讲解推荐)

目录 暴力做法 代码如下 KMP算法 不同的next求法-----视频讲解/博客推荐 视频推荐 博客推荐 课本上的方法- prefix的方法- 求next数组思路---next数组存放前缀表的方式 s和p匹配思路 代码如下 暴力做法 遍历s主串中每一个元素&#xff0c;如果该元素等于模板串p中…...

JSON 简介

JSON是什么&#xff1f;(了解) JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式&#xff0c;常用于Web应用程序之间的数据传输。 JSON格式是一种文本格式&#xff0c;用于描述数据的结构和内容。它由两种基本元素组成&#xff1a;键值对和…...

Impala4.x源码阅读笔记(三)——Impala如何管理Iceberg表元数据

前言 本文为笔者个人阅读Apache Impala源码时的笔记&#xff0c;仅代表我个人对代码的理解&#xff0c;个人水平有限&#xff0c;文章可能存在理解错误、遗漏或者过时之处。如果有任何错误或者有更好的见解&#xff0c;欢迎指正。 上一篇文章Impala4.x源码阅读笔记&#xff0…...

Ubuntu2204配置samba

0.前情说明 samba服务器主要是用来局域网共享文件的&#xff0c;如果想公网共享可能行不通&#xff0c;我已经踩坑一天了 所以说如果你想满足公网samba共享你就可以不要看下去了 1.参考连接 Ubuntu 安装 Samba 服务器_ubuntu安装samba服务器-CSDN博客 2.安装samba服务 sud…...

AVL树(超详解)

文章目录 前言AVL树的概念AVL树的实现定义AVL树insert 单旋左单旋右单旋左单旋代码右单旋代码 双旋左右双旋右左双旋 测试AVL树的性能 前言 AVL树是怎么来的呢&#xff1f; 我们知道搜索二叉树会存在退化问题&#xff0c;退化以后就变成单支或者接近单支。 它的效率就变成O(N)…...

禁止浏览器记住密码和自动填充 element-ui+vue

vue 根据element-ui 自定义密码输入框&#xff0c;防止浏览器 记住密码和自动填充 <template><divclass"el-password el-input":class"[size ? el-input-- size : , { is-disabled: disabled }]"><inputclass"el-input__inner"…...

K8s实战-init容器

概念&#xff1a; 初始化容器的概念 比如一个容器A依赖其他容器&#xff0c;可以为A设置多个 依赖容易A1&#xff0c;A2&#xff0c;A3 A1,A2,A3要按照顺序启动&#xff0c;A1没有启动启动起来的 话&#xff0c;A2,A3是不会启动的&#xff0c;直到所有的静态容器全 部启动完毕…...

Vue3.2 自定义指令详解与实战

一、介绍 在Vue3中&#xff0c;自定义指令为开发者提供了一种灵活的方式来扩展Vue的HTML模板语法&#xff0c;使其能够执行特定的DOM操作或组件逻辑。不同于Vue2.x中的全局和局部指令注册方式&#xff0c;Vue3引入了Composition API&#xff0c;这使得自定义指令的编写和使用更…...

XV-3510CB振动陀螺仪传感器

XV-3510CB传感器是一款振动陀螺仪传感器&#xff0c;具有卓越的稳定性和可靠性&#xff0c;超小的封装尺寸SMD53.21.3mm&#xff0c;密封提供了良好的可持续环保能力&#xff0c;采用振动晶体&#xff0c;该传感器具有稳定的性能和超长的寿命。振动晶体的振动能够提供更为精确的…...

设计模式Java向

设计原则&#xff1a; 开闭原则&#xff1a; 用例对象和提供抽象功能进行分割&#xff0c;用例不变&#xff0c;抽象功能被实现&#xff0c;用于不断的扩展&#xff0c;于是源代码不需要进行修改&#xff0c;只在原有基础上进行抽象功能的实现从而进行代码扩展。不变源于代码…...

图片素材管理软件Eagle for mac提高素材整理维度

Eagle for mac是一款图片素材管理软件&#xff0c;支持藏网页图片&#xff0c;网页截屏&#xff0c;屏幕截图和标注&#xff0c;自动标签和筛选等功能&#xff0c;让你设计师方便存储需要的素材和查找&#xff0c;提供工作效率。 Eagle mac软件介绍 Eagle mac帮助你成为更好、…...

Transformer各模块结构详解(附图)

前言&#xff1a;基于TRANSFORMER的结构在视觉领域是承上启下的作用。刚接触会比较难&#xff0c;上的话需要对RNN&#xff0c;LSTM&#xff0c;ATTENTION先有初步的了解。下的话需要学习VIT&#xff0c;GPT&#xff0c;DETR等结构先了解TRANSFORMER都是必要的。 参考&#xff…...

Python遥感影像深度学习指南(2)-在 PyTorch 中创建自定义数据集和加载器

在上一篇 文章中,我们Fast.ai 在卫星图像中检测云轮廓,检测物体轮廓被称为语义分割。虽然我们用几行代码就能达到 96% 的准确率,但该模型无法考虑数据集中提供的所有输入通道(红、绿、蓝和近红外)。问题在于,深度学习框架(如 Keras、Fast.ai 甚至 PyTorch)中的大多数语…...

韩版传奇 2 源码分析与 Unity 重制(三)客户端渲染管线

专题介绍 该专题将会分析 LOMCN 基于韩版传奇 2,使用 .NET 重写的传奇源码(服务端 + 客户端),分析数据交互、状态管理和客户端渲染等技术,此外笔者还会分享将客户端部分移植到 Unity 和服务端用现代编程语言重写的全过程。 概览 在这一篇文章中,我们将开始分析传奇客户…...

深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第三节 栈与堆,值类型与引用类型

深入浅出图解C#堆与栈 C# Heaping VS Stacking 第三节 栈与堆&#xff0c;值类型与引用类型 [深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第一节 理解堆与栈](https://mp.csdn.net/mdeditor/101021023)[深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第二节 栈基本工…...

分享好用的chatgpt

1.在vscode中&#xff0c;点击这个&#xff1a; 2.搜索&#xff1a;ChatGPT - 中文版&#xff0c;个人觉得这个更好用&#xff1a; 3.下载完成之后&#xff0c;左侧会多出来这个&#xff1a; 点击这个图标就能进入chatgpt界面了 4.如果想使用tizi访问国外的chatgpt&#xf…...

【小白专用】C# 压缩文件 ICSharpCode.SharpZipLib.dll效果:

插件描述&#xff1a; ICSharpCode.SharpZipLib.dll 是一个完全由c#编写的Zip, GZip、Tar 、 BZip2 类库,可以方便地支持这几种格式的压缩解压缩, SharpZipLib 的许可是经过修改的GPL&#xff0c;底线是允许用在不开源商业软件中&#xff0c;意思就是免费使用。具体可访问ICSha…...

Protobuf 编码规则及c++使用详解

Protobuf 编码规则及c使用详解 Protobuf 介绍 Protocol Buffers (a.k.a., protobuf) are Google’s language-neutral, platform-neutral, extensible mechanism for serializing structured data Protocol Buffers&#xff08;简称为protobuf&#xff09;是谷歌的语言无关、…...

Kafka优异的性能是如何实现的?

Apache Kafka是一个分布式流处理平台&#xff0c;设计用来处理高吞吐量的数据。它被广泛用于构建实时数据管道和流式应用程序。Kafka之所以能够提供优秀的性能和高吞吐量&#xff0c;主要得益于以下几个方面的设计和实现&#xff1a; 1. 分布式系统设计 Kafka是一个分布式系统…...

(二)MaterializedMySQL具体实施步骤举例

要将 MySQL 中的 test 数据库实时同步到位于同一台服务器&#xff08;IP 地址为 192.168.197.128&#xff09;上的 ClickHouse&#xff0c;您可以使用 MaterializedMySQL 引擎。以下是详细的步骤&#xff1a; 1. 准备工作 确保您的 MySQL 和 ClickHouse 服务都在运行&#xf…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…...

React 第五十五节 Router 中 useAsyncError的使用详解

前言 useAsyncError 是 React Router v6.4 引入的一个钩子&#xff0c;用于处理异步操作&#xff08;如数据加载&#xff09;中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误&#xff1a;捕获在 loader 或 action 中发生的异步错误替…...

汽车生产虚拟实训中的技能提升与生产优化​

在制造业蓬勃发展的大背景下&#xff0c;虚拟教学实训宛如一颗璀璨的新星&#xff0c;正发挥着不可或缺且日益凸显的关键作用&#xff0c;源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例&#xff0c;汽车生产线上各类…...

第25节 Node.js 断言测试

Node.js的assert模块主要用于编写程序的单元测试时使用&#xff0c;通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试&#xff0c;通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理

引言 Bitmap&#xff08;位图&#xff09;是Android应用内存占用的“头号杀手”。一张1080P&#xff08;1920x1080&#xff09;的图片以ARGB_8888格式加载时&#xff0c;内存占用高达8MB&#xff08;192010804字节&#xff09;。据统计&#xff0c;超过60%的应用OOM崩溃与Bitm…...

Java编程之桥接模式

定义 桥接模式&#xff08;Bridge Pattern&#xff09;属于结构型设计模式&#xff0c;它的核心意图是将抽象部分与实现部分分离&#xff0c;使它们可以独立地变化。这种模式通过组合关系来替代继承关系&#xff0c;从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...

LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》

这段 Python 代码是一个完整的 知识库数据库操作模块&#xff0c;用于对本地知识库系统中的知识库进行增删改查&#xff08;CRUD&#xff09;操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 &#x1f4d8; 一、整体功能概述 该模块…...

HybridVLA——让单一LLM同时具备扩散和自回归动作预测能力:训练时既扩散也回归,但推理时则扩散

前言 如上一篇文章《dexcap升级版之DexWild》中的前言部分所说&#xff0c;在叠衣服的过程中&#xff0c;我会带着团队对比各种模型、方法、策略&#xff0c;毕竟针对各个场景始终寻找更优的解决方案&#xff0c;是我个人和我司「七月在线」的职责之一 且个人认为&#xff0c…...

CSS 工具对比:UnoCSS vs Tailwind CSS,谁是你的菜?

在现代前端开发中&#xff0c;Utility-First (功能优先) CSS 框架已经成为主流。其中&#xff0c;Tailwind CSS 无疑是市场的领导者和标杆。然而&#xff0c;一个名为 UnoCSS 的新星正以其惊人的性能和极致的灵活性迅速崛起。 这篇文章将深入探讨这两款工具的核心理念、技术差…...