【算法练习Day8】 kmp算法找出字符串中第一个匹配项的下标反转字符串中的单词重复的子字符串

、​在这里插入图片描述

​📝个人主页:@Sherry的成长之路
🏠学习社区:Sherry的成长之路(个人社区)
📖专栏链接:练题
🎯长路漫漫浩浩,万事皆有期待

文章目录

  • kmp算法
  • 找出字符串中第一个匹配项的下标
  • 重复的子字符串
    • 移动匹配
    • kmp算法
  • 总结:

kmp算法

kmp算法是一种快速查找字符串的算法,主要用途是在一个字符串里查找是否包含另一个字符串,kmp在理解上不是很友好,首先我们要搞清楚什么是前后缀、最长相等前后缀、前缀表、next数组如何实现前缀表,最后就是kmp算法借助前缀表的实现。

前后缀的概念

前缀就是包含第一个字符,而不包含最后一个字符的所有字串都可以被称为前缀。

后缀是包含最后一个字符,且不包含第一个字符的所有字串都可以被称为后缀。

举个例子:hello 前缀可以是h,he,hel,hell 后缀可以是:e,el,ell,ello

最长相等前后缀

最长相等前后缀顾名思义,就是前后缀相等的情况下,我们取最长的那一段。

前缀表,next数组如何实现?

前缀表十分重要,它是KMP算法的核心思想,先说它的作用,它的作用是实现匹配字符串时,如果遇到主串(用于对比的字符串)和模式串(拿来做对比的字符串)某个字符不相等时,将指针返回到上一个最长相等前后缀处再进行对比,这样做的好处是可以使字符不相等时退回某处,而不至于像暴力求解一样一遇到不相等就要重头对比,在主串有一定规律时,此方法显得十分方便。

下面我们再来说一说实现的方法:
定义一个数组名字叫next数组,网上大体有三种方法,第一种就是数组正常存储返回地址,第二种数组存储返回地址-1,第三种将返回地址整体向左移动。

我们说到next数组就是一个前缀表,它来存我们字符串里字符匹配失败时,应该返回的位置用第二种方法实际上是返回到最长相等前缀的位置

void getNext(int* next, const string& s){int j = -1;next[0] = j;for(int i = 1; i < s.size(); i++) { // 注意i从1开始while (j >= 0 && s[i] != s[j + 1]) { // 前后缀不相同了j = next[j]; // 向前回退}if (s[i] == s[j + 1]) { // 找到相同的前后缀j++;}next[i] = j; // 将j(前缀的长度)赋给next[i]}
}

这一段就是c++的前缀表代码段,我们用j来表示前缀的最长长度为多少,i来向后遍历,当我们这个字符串的两个位置不相等时,判断j是否大于0,因为要涉及到j-1,只要两个位置不相等就使j一直回退,如果两位置相等,那么j向前走一步,意为最长长度加1,然后在数组每一个位置,记录当前匹配失败时,回退到那个位置。

关于kmp算法的使用我们来看具体的例题。

找出字符串中第一个匹配项的下标

28. 找出字符串中第一个匹配项的下标 - 力扣(LeetCode)

这道题就是典型可以应用kmp算法的题型

class Solution {
public:void getNext(int* next, const string& s) {int j = -1;next[0] = j;for(int i = 1; i < s.size(); i++) { // 注意i从1开始while (j >= 0 && s[i] != s[j + 1]) { // 前后缀不相同了j = next[j]; // 向前回退}if (s[i] == s[j + 1]) { // 找到相同的前后缀j++;}next[i] = j; // 将j(前缀的长度)赋给next[i]}}int strStr(string haystack, string needle) {if (needle.size() == 0) {return 0;}int next[needle.size()];getNext(next, needle);int j = -1; // // 因为next数组里记录的起始位置为-1for (int i = 0; i < haystack.size(); i++) { // 注意i就从0开始while(j >= 0 && haystack[i] != needle[j + 1]) { // 不匹配j = next[j]; // j 寻找之前匹配的位置}if (haystack[i] == needle[j + 1]) { // 匹配,j和i同时向后移动j++; // i的增加在for循环里}if (j == (needle.size() - 1) ) { // 文本串s里出现了模式串treturn (i - needle.size() + 1);}}return -1;}
};

第一部分的代码就是上面所说的前缀和,后面的是用循环来遍历,也就是应用前缀和数组next,遍历查找,如果两字符串某个字符不相等,那么就使j一直回退,相等时候j++,当j++到模式串的最后一个字符了,则说明该字符串在主串中,由于字符不相同时,只有j会回退,i仍然向前走,所以当i走完全部,j还没有到到最后一个字符,说明该字符串不存在于主串内。

重复的子字符串

459. 重复的子字符串 - 力扣(LeetCode)

移动匹配

判断字符串s是否由重复子串组成,只要两个s拼接在一起,里面还出现一个s的话,就说明是由重复子串组成。当然,我们在判断 s + s 拼接的字符串里是否出现一个s的的时候,要刨除 s + s 的首字符和尾字符,这样避免在s+s中搜索出原来的s,我们要搜索的是中间拼接出来的s。

class Solution {
public:bool repeatedSubstringPattern(string s) {string t = s + s;t.erase(t.begin()); t.erase(t.end() - 1); // 掐头去尾if (t.find(s) != std::string::npos) return true; // rreturn false;}
};

kmp算法

这道题刚看的时候,不太像使用kmp算法的题目,但是可以用kmp算法,其中是有一些技巧的:字符串的相等前后缀,错开的那一部分则为重复子串,用该重复子串重复n次,则可以取得原字符串。这个结论可以模拟一下。用next数组模拟,数组中最后一位存取的就是最长前后缀的长度,用字符串总长度,对总长度减去最长前后缀的长度,再取模,如果能整除,则该字符串是由前x个字符由n次变换得到,若不能整除则说明字符串不是由重复字串得到的。这里使用了前缀表统一减一的实现方式:

class Solution {
public:void getNext (int* next, const string& s){next[0] = -1;int j = -1;for(int i = 1;i < s.size(); i++){while(j >= 0 && s[i] != s[j + 1]) {j = next[j];}if(s[i] == s[j + 1]) {j++;}next[i] = j;}}bool repeatedSubstringPattern (string s) {if (s.size() == 0) {return false;}int next[s.size()];getNext(next, s);int len = s.size();if (next[len - 1] != -1 && len % (len - (next[len - 1] + 1)) == 0) {return true;}return false;}
};

总结:

今天我们进行了字符串的复习和双指针的回顾,还有kmp算法的应用,kmp算法还是挺有难度的,相关的思想需要多复习回顾。接下来,我们继续进行算法练习·。希望我的文章和讲解能对大家的学习提供一些帮助。

当然,本文仍有许多不足之处,欢迎各位小伙伴们随时私信交流、批评指正!我们下期见~

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ubuntu18.04 OpenGL开发(显示YUV)

源码参考&#xff1a;https://download.csdn.net/download/weixin_55163060/88382816 安装opengl库 sudo apt install libglu1-mesa-dev freeglut3-dev mesa-common-dev 安装opengl工具包 sudo apt install mesa-utils 检查opengl版本信息&#xff08;桌面终端执行&#xff09…

UWB技术在汽车智能制造的应用

返修区车辆管理项目 应用背景 在车辆总装生产线中&#xff0c;车辆下线后检测与返修是最后一个关键环节&#xff0c;整车一旦下线&#xff0c;由于流水线装配工艺、来料等原因&#xff0c;可能会出现部分整车存在瑕疵&#xff0c;进而进入返修区域待检。由于可能出现问题的不确…

【EI会议征稿】第三届机械、建模与材料工程国际学术会议(I3ME 2023)

第三届机械、建模与材料工程国际学术会议&#xff08;I3ME 2023&#xff09; 2023 3rd International Conference on Mechanical, Modeling and Materials Engineering 第三届机械、建模与材料工程国际学术会议&#xff08;I3ME 2023&#xff09;将于2023年12月1-3日在中国长春…

五子棋AI算法和开局定式(直指13式)破解

五子棋AI算法和开局定式&#xff08; 直指13式 &#xff09;破解 先前发了几篇五子棋游戏程序设计的博文&#xff0c;设计了游戏程序&#xff0c;也设计了AI智能奕棋的算法&#xff0c;运行程序检测算法的可行性&#xff0c;完成人机模式游戏功能的设置。这还不够&#xff0c;…

十六.镜头知识之工业镜头的质量判断因素

十六.镜头知识之工业镜头的质量判断因素 文章目录 十六.镜头知识之工业镜头的质量判断因素1.分辨率(Resolution)2.明锐度(Acutance)3.景深(DOF)&#xff1a;4. 最大相对孔径与光圈系数5.工业镜头各参数间的相互影响关系5.1.焦距大小的影响情况5.2.光圈大小的影响情况5.3.像场中…

WebPack5进阶使用总结(二)

WebPack5进阶使用总结 1、处理js资源1.1、Eslint1.2、在webpack中使用Eslint1.3、Babel1.4、在webpack中使用 2、处理HTML资源3、开发服务器&自动化4、生产模式介绍5、Css处理5.1、Css兼容性处理5.2、合并配置5.3、Css压缩 配套视频&#xff1a;尚硅谷Webpack5入门到原理 配…

STM32H7系列MPU与CACHE以及RAM

一、启用cache 启用cache很简单&#xff0c;就是这两句&#xff0c;分别打开I-Cache和D-Cache&#xff0c;但是如果只使用这两句&#xff0c;再操作DMA和FLASH时就很有可能遇到问题&#xff0c;后面会具体说明。 SCB_EnableICache();//使能I-CacheSCB_EnableDCache();//使能D-…

Android studio “Layout Inspector“工具在Android14 userdebug设备无法正常使用

背景描述 做rom开发的都知道&#xff0c;“Layout Inspector”和“Attach Debugger to Android Process”是studio里很好用的工具&#xff0c;可以用来查看布局、调试系统进程&#xff08;比如setting、launcher、systemui&#xff09;。 问题描述 最进刚开始一个Android 14…

现代数据架构-湖仓一体

当前的数据架构已经从数据库、数据仓库&#xff0c;发展到了数据湖、湖仓一体架构&#xff0c;本篇文章从头梳理了一下数据行业发展的脉络。 上世纪&#xff0c;最早出现了关系型数据库&#xff0c;也就是DBMS&#xff0c;有商业的Oracle、 IBM的DB2、Sybase、Informix、 微软…

【数据结构初阶】六、线性表中的队列(链式结构实现队列)

相关代码gitee自取&#xff1a; C语言学习日记: 加油努力 (gitee.com) 接上期&#xff1a; 【数据结构初阶】五、线性表中的栈&#xff08;顺序表实现栈&#xff09;_高高的胖子的博客-CSDN博客 1 . 队列&#xff08;Queue&#xff09; 队列的概念和结构&#xff1a; 队列…

PSINS工具箱学习(一)下载安装初始化、SINS-GPS组合导航仿真、习惯约定与常用变量符号、数据导入转换、绘图显示

原始 Markdown文档、Visio流程图、XMind思维导图见&#xff1a;https://github.com/LiZhengXiao99/Navigation-Learning 文章目录 一、前言二、相关资源三、下载安装初始化1、下载PSINSyymmdd.rar工具箱文件2、解压文件3、初始化4、启动工具箱导览 四、习惯约定与常用变量符号1…

数据集笔记:2015上海地铁一卡通数据

数据地址&#xff1a;上海地铁数据_免费高速下载|百度网盘-分享无限制 (baidu.com) 数据介绍 上海2015年几天的地铁一卡通出入站信息 卡号、交易日期、交易时间、公交线路/地铁站点中文名称、行业名称(公交、地铁、出租、轮渡、PR停车场)、交易金额、交易性质(非优惠、优惠、…

No139.精选前端面试题,享受每天的挑战和学习

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…

RNN模型与NLP应用(1/9):数据处理基础Data Processing Basics

文章目录 处理分类特征把分类特征转化为数值特征应用one-hot编码indice要从1开始而不能从0开始数据处理为什么使用one-hot向量 处理文本数据Step1&#xff1a;将文本分割成单词Step2&#xff1a;计算单词的频度按频度递减的方式排序 Step3&#xff1a;One-Hot编码 处理分类特征…

UE5 ChaosVehicles载具研究

一、基本组成 载具Actor类名称&#xff1a;WheeledVehiclePawn Actor最原始的结构 官方增加了两个摇臂相机&#xff0c;可以像驾驶游戏那样切换多机位、旋转观察 选择骨骼网格体、动画蓝图类、开启物理模拟 二、SportsCar_Pawn 角阻尼&#xff1a;物体旋转的阻力。数值越大…

前端架构师之02_ES6_高级

1 类和继承 1.1 class类 JavaScript 语言中&#xff0c;生成实例对象的传统方法是通过构造函数。 // ES5 创建对象 // 创建一个类&#xff0c;用户名 密码 function User(name,pass){// 添加属性this.name name;this.pass pass; } // 用 原型 添加方法 User.prototype.sho…

Docker下如何构建包含延迟插件的RabbitMQ镜像

&#x1f468;&#x1f3fb;‍&#x1f4bb; 热爱摄影的程序员 &#x1f468;&#x1f3fb;‍&#x1f3a8; 喜欢编码的设计师 &#x1f9d5;&#x1f3fb; 擅长设计的剪辑师 &#x1f9d1;&#x1f3fb;‍&#x1f3eb; 一位高冷无情的编码爱好者 大家好&#xff0c;我是 DevO…

FIPS 140简介

FIPS 140(Federal Information Processing Standards Publication 140)是美国联邦政府颁布的一系列密码学标准,用于评估和验证安全模块(如加密模块)的安全性。FIPS 140标准制定了一系列安全要求,以确保加密模块能够提供足够的安全性,以保护敏感数据。 与AES的关系是,A…

UE5 虚幻引擎 如何使用构造脚本(Construction Script)? 构造脚本的奥秘!

目录 1 构造脚本&#xff08;Construction Script&#xff09;1.1 介绍1.2 案例1&#xff1a;利用样条组件程序化生成树木1.2 案例2&#xff1a;利用样条组件和样条网格体组件程序化生成道路 1 构造脚本&#xff08;Construction Script&#xff09; 1.1 介绍 问题&#xff1a…

3D孪生场景搭建:模型阵列摆放

阵列摆放概念 阵列摆放是指将物体、设备或元件按照一定的规则和间距排列组合的方式。在工程和科学领域中&#xff0c;阵列式摆放常常用于优化空间利用、提高效率或增强性能。 阵列摆放通常需要考虑间距、角度、方向、对称性等因素&#xff0c;以满足特定的要求和设计目标。不同…