算法力扣刷题 二十五【28.找出字符串中第一个匹配项的下标】

前言

字符串篇,继续。
记录 二十五【28.找出字符串中第一个匹配项的下标】


一、题目阅读

给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。

示例 1:

输入:haystack = "sadbutsad", needle = "sad"
输出:0
解释:"sad" 在下标 0 和 6 处匹配。
第一个匹配项的下标是 0 ,所以返回 0 。

示例 2:

输入:haystack = "leetcode", needle = "leeto"
输出:-1
解释:"leeto" 没有在 "leetcode" 中出现,所以返回 -1 。

提示:

1 <= haystack.length, needle.length <= 104
haystack 和 needle 仅由小写英文字符组成

二、尝试实现

思路一

第一反应遍历haystack,如果首字母匹配,固定i;开启第二层循环,看是否全字匹配。应该可以。尝试。
(1)第一次尝试,遇到的问题:

class Solution {
public:int strStr(string haystack, string needle) {for(int i = 0;i < haystack.size();i++){if(haystack[i] == needle[0]){int k = 1;//指针指向needlefor(int j = i+1;j < haystack.size();j++){if(k < needle.size() && haystack[j] != needle[k++]){i = j;break;    }else if(k == needle.size()){return i;}}}}return -1;}
};
  • int k = 1;找到第一个字母匹配,想从第二个字母开始判断。所以j = i +1。return i在第二层for循环里面,这是默认haystack有2个及以上的字母。如果haystack是单个字母,无法进入j的遍历。如下case不成立:

      haystack ="a";needle =	"a"。这个case无法通过。
    

    所以,第一次修正。

(2)第二次尝试,修正第一个问题:

class Solution {
public:int strStr(string haystack, string needle) {for(int i = 0;i < haystack.size();i++){if(haystack[i] == needle[0]){int k = 0;//指针指向needlefor(int j = i;j < haystack.size();j++){if(k < needle.size() && haystack[j] != needle[k++]){	//等式不成立,不影响k++操作i = j;break;    }else if(k == needle.size()){	//因为判断是否相等时操作k++,最后k会超出needle的下标,所以上面k < needle.size()也要判断return i;}}}}return -1;}
};
  • 这一遍出现的问题:i =j;以为从i起始,往后长度是needle和needle单词不是全字匹配,就空掉j个长度。可能是交叉出现的,例如下面case:

      haystack ="mississippi";needle ="issip"。错误原因:但i = 1,j = 5因为不相等,需要break;但把i = j ,跳过正确答案return 4.
    

    所以i要一步一步往后走,不能跳过。

(3)再次修正

class Solution {
public:int strStr(string haystack, string needle) {for(int i = 0;i < haystack.size();i++){if(haystack[i] == needle[0]){int k = 0;//指针指向needlefor(int j = i;j < haystack.size();j++){if(k < needle.size() && haystack[j] != needle[k++]){break;    }else if(k == needle.size()){return i;}// k++;如果k++放到这里,if里面的k++要取消,同时,k == needle.size()-1。}}}return -1;}
};

本次测试通过,完成实现


三、代码随想录学习

学习内容

KMP算法——解决字符串匹配的问题。在“文本串”中找“模式串”。对应题目:haystack是“文本串”;needle是“模式串”。

(1)为什么KMP算法找字符串匹配能更快?
答:

  • 二、中的代码就是暴力实现。i在文本串中一步一步后移,第一个if判断haystack[i]和needle[0]比较。所以如果不是全字匹配,i后移一位,重新和needle[0]比较。总结:每轮遇到不相等的字母,新开一轮,和模式串的初始位置比较

  • 新开一轮后,如果能从模式串中间的某个位置继续比较,看起来比重头来过要好。那咋知道遇到不相等字母时,从中间的哪个位置开始呢?跳到哪个下标可以继续呢?答案:

  • 前缀表。解释:它是一个数组,起个名字叫“next”。长度和模式串的长度一样。如果当前位置字母不相等,查看前一个位置的前缀表数值,跳转到该下标。假设从B位置跳到A位置,说明A位置之前的区间(不包含A)等同于从B位置往前数长度A这个区间(看图)。
    在这里插入图片描述
    (2)发现:从下标6跳转到下标2,下标2前面的区间(不包含2):c a。和从下标6往前数2个的区间:c a一样。

      对于“cacbca”:前缀和后缀相等的最长长度是2:前缀=c a。后缀=c a(不能是a c,所以不是对称的意思)
    

(3)原理:

位置B跳转到位置A——

  • A之前的区间(不包含A) ,这段长度为x。
  • B往前数长度x,不包含B的区间。(下图展示了两段区间)
  • 以上两个范围内容一模一样,也就是包含j-1的区间中前缀和后缀一样。找前缀=后缀长度的最大值,为了回退最少。
    在这里插入图片描述

代码实现

前缀表的数值不做任何改动,也不去右移/减1再加1。遇到不相等的位置,就看前一个元素前缀表数值多少,跳转到对应下标。

class Solution {
public:void getNext(int* next,string& s){next[0] = 0;//第一位没有前缀int j = 0;//前缀=后缀最长时,j指向前缀的末尾。也就是往next里面放的值。for(int i = 1;i < s.size();i++){while(j > 0 && s[j] != s[i]){j = next[j-1];}if(s[j] == s[i]){   //前缀=后缀最长时,可能中间有重叠。j++;}next[i] = j;}}int strStr(string haystack, string needle) {int size = needle.size();int* next = new int[size]{0};getNext(next,needle);//用这个函数来获取前缀表,传进去一个数组用来装值,和处理的字符串for(int i = 0;i < size;i++){cout<<next[i]<<'\t';}int j = 0;for(int i = 0;i < haystack.size();i++){while(j > 0 && needle[j] != haystack[i]){j = next[j-1];}if(haystack[i] == needle[j]){j++;}if(j == needle.size()){delete[] next;return (i-needle.size()+1);}}delete[] next;return -1;}
};

(1)问题:为什么求前缀表当i和j不相等时,j = next[j-1],而不是j一点一点的往前退,可以一下跳转到next[j-1]?
答:细想绿色两段相同,并且是最大长度下的相同
@danaaaaa


总结

  • KMP算法解决匹配问题。当遇到不匹配项回退重新比较可以不用从头开始,可以在中间的某个位置继续进行。
  • 如何确定在哪个位置继续比较?用前缀表。前缀表保证:从下标B跳转到下标A,0~ (A-1)下标范围和(B-A)~(B-1)下标范围内容一样,可以不再重复比较。
  • 求前缀表的时候:初始化——当s[j] != s[i]时,跳转到下标=next[j-1]处;——当s[j] == s[i] 时,j++,前缀增加一位。

(欢迎指正,转载标明出处)

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

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

相关文章

C语言中的基础指针操作

在C语言中&#xff0c;指针是一个非常重要的概念&#xff0c;它提供了直接访问内存地址的能力。指针变量用于存储内存地址&#xff0c;而不是数据值&#xff0c;在某种意义上和门牌号具有相似含义&#xff1a;指针是一个变量&#xff0c;其存储的是另一个变量的内存地址&#x…

java之动态代理

1 代理模式 代理模式提供了对目标对象额外的访问方式&#xff0c;即通过代理对象访问目标对象&#xff0c;这样可以在不修改原目标对象的前提下&#xff0c;提供额外的功能操作&#xff0c;扩展目标对象的功能。简言之&#xff0c;代理模式就是设置一个中间代理来控制访问原目标…

网络io与select,poll,epoll

前言 网络 IO&#xff0c;会涉及到两个系统对象&#xff0c;一个是用户空间调用 IO 的进程或者线程&#xff0c;另一个是内核空间的内核系统&#xff0c;比如发生 IO 操作 read 时&#xff0c;它会经历两个阶段&#xff1a; 1. 等待数据准备就绪 2. 将数据从内核拷贝到进程或…

网络编程常见问题

1、TCP状态迁移图 2、TCP三次握手过程 2.1、握手流程 1、TCP服务器进程先创建传输控制块TCB&#xff0c;时刻准备接受客户进程的连接请求&#xff0c;此时服务器就进入了LISTEN&#xff08;监听&#xff09;状态&#xff1b; 2、TCP客户进程也是先创建传输控制块TCB&#xff…

改进经验模态分解方法-通过迭代方式(IMF振幅加权频率,Python)

一种新颖的改进经验模态分解方法-通过迭代方式&#xff08;IMF振幅加权频率&#xff09;有效缓解了模态混叠缺陷&#xff0c;以后慢慢讲&#xff0c;先占坑。 import numpy as np import matplotlib.pyplot as plt import os import seaborn as sns from scipy import stats i…

C语言图书管理系统控制台程序

程序示例精选 C语言图书管理系统控制台程序 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对《C语言图书管理系统控制台程序》编写代码&#xff0c;代码整洁&#xff0c;规则&#xff0c;易读…

加密与安全_三种方式实现基于国密非对称加密算法的加解密和签名验签

文章目录 国际算法基础概念常见的加密算法及分类签名和验签基础概念常见的签名算法应用场景 国密算法对称加密&#xff08;DES/AES⇒SM4&#xff09;非对称加密&#xff08;RSA/ECC⇒SM2&#xff09;散列(摘要/哈希)算法&#xff08;MD5/SHA⇒SM3&#xff09; Code方式一 使用B…

智慧园区综合平台解决方案PPT(75页)

## 智慧园区的理解 ### 从园区1.0到园区4.0的演进 1. 园区1.0&#xff1a;以土地经营为主&#xff0c;成本驱动&#xff0c;提供基本服务。 2. 园区2.0&#xff1a;服务驱动&#xff0c;关注企业成长&#xff0c;提供增值服务。 3. 园区3.0&#xff1a;智慧型园区&#xff…

机器学习引领教育革命:智能教育的新时代

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀目录 &#x1f4d2;1. 引言&#x1f4d9;2. 机器学习在教育中的应用&#x1f31e;个性化学习&#x1f319;评估与反馈的智能化⭐教学资源的优…

STC89C52RC单片机设计的FM收音机+自动搜台+存储电台(程序+原理图+PCB)

资料下载地址&#xff1a;STC89C52RC单片机设计的FM收音机自动搜台存储电台&#xff08;程序原理图PCB) 1、实物图 2、部分程序 #include <reg52.h> #include "tea5767.h" #include "delay.h" #include "lcd1602.h" //K1:上一台 K2:下一…

mac电脑游戏推荐:NBA 2K24 街机版下载

NBA 2K24 街机版是一款由2K Sports开发并发行的篮球游戏&#xff0c;属于著名的NBA 2K系列。这款游戏为玩家提供了与NBA联赛中真实球员和球队互动的机会&#xff0c;体验篮球比赛的激情与紧张。街机版的NBA 2K24通常会在游戏厅、商场等公共场所设置&#xff0c;供玩家投币游玩。…

c++重载(运算符)

1&#xff09;C入门级小知识&#xff0c;分享给将要学习或者正在学习C开发的同学。 2&#xff09;内容属于原创&#xff0c;若转载&#xff0c;请说明出处。 3&#xff09;提供相关问题有偿答疑和支持。 对于系统的所有操作符&#xff0c;一般情况下&#xff0c;只支持基本数…

AWTK 用 icon_at 属性设置图标位置

1. style 在 style 文件中通过 icon_at 属性设置图标位置。 <style name"right_bottom" icon_at"right_bottom"><normal icon"unchecked_right_bottom" /><pressed icon"unchecked_right_bottom" /><over i…

redis实战-短信登录

基于session的登录流程 session的登录流程图 1. 发送验证码 用户在提交手机号后&#xff0c;会校验手机号是否合法&#xff0c;如果不合法&#xff0c;则要求用户重新输入手机号 如果手机号合法&#xff0c;后台此时生成对应的验证码&#xff0c;同时将验证码进行保存&#x…

第一节:如何开发第一个spring boot3.x项目(自学Spring boot 3.x的第一天)

大家好&#xff0c;我是网创有方&#xff0c;从今天开始&#xff0c;我会记录每篇我自学spring boot3.x的经验。只要我不偷懒&#xff0c;学完应该很快&#xff0c;哈哈&#xff0c;更新速度尽可能快&#xff0c;想和大佬们一块讨论&#xff0c;如果需要讨论的欢迎一起评论区留…

Pytorch实战(二)

文章目录 前言一、LeNet5原理1.1LeNet5网络结构1.2LeNet网络参数1.3LeNet5网络总结 二、AlexNext2.1AlexNet网络结构2.2AlexNet网络参数2.3Dropout操作2.4PCA图像增强2.5LRN正则化2.6AlexNet总结 三、实战3.1LeNet5模型搭建3.2模型训练 前言 参考原视频&#xff1a;哔哩哔哩。 …

【后端面试题】【中间件】【NoSQL】ElasticSearch面试基本思路和高可用方案(限流、消息队列、协调节点、双集群)

基本思路 业务开发面试Elasticsearch的时候基本问的是基础知识以及倒排索引。 Elasticsearch最基本的可用性保障就是分片&#xff0c;而且是主从分片&#xff0c;所以遇到Elasticsearch如何做到高可用这个问题的时候&#xff0c;首先要提到这一点。 Elasticsearch高可用的核心…

手机屏幕贴合项目(ni视觉如何找矩形的角坐标)

首先&#xff0c;我们存储了cg和dito感兴趣八个角图像的模板&#xff0c;用来匹配位置。 cover指的是cg的四个角模板&#xff0c;lcm是dito四个角匹配模板。 其次&#xff0c;我们采集的8副图像&#xff08;m_DlgCCDViewArr[2][4]&#xff09;中一定包含匹配模板的特征。 好&…

Json与Java类

简介 JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式&#xff0c;易于人阅读和编写&#xff0c;同时也易于机器解析和生成。JSON数据由键值对构成&#xff0c;并以易于阅读的文本形式展现&#xff0c;支持数组、对象、字符串、数字、布尔值…

笔灵AI写作:释放创意,提升写作效率的秘诀

内容为王&#xff0c;在内容创作的世界中尤为重要。然而&#xff0c;面对写作时常常感到无从下手&#xff1a;有时缺乏灵感&#xff0c;有时难以表达清楚自己的想法。AI写作助手的出现&#xff0c;为这些问题提供了创新的解决方案&#xff0c;极大地改变了内容创作的过程。 今…