算法力扣刷题 二十五【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,一经查实,立即删除!

相关文章

RESTful Web 服务详解

RESTful Web 服务是一种基于 Representational State Transfer (REST) 架构风格的 Web 服务&#xff0c;它利用 HTTP 协议来传输数据&#xff0c;支持多种数据格式如 JSON 和 XML。在 Spring 框架中&#xff0c;通过简单配置和注解可以轻松实现 RESTful Web 服务。在本文中&…

C语言中的基础指针操作

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

java之动态代理

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

超级对齐是什么?

超级对齐是一个在人工智能&#xff08;AI&#xff09;领域中的概念&#xff0c;其定义和重要性可以从以下几个方面来清晰地阐述&#xff1a; 1. **定义**&#xff1a; - 超级对齐是指确保在所有领域都超越人类智能的超级人工智能&#xff08;AI&#xff09;系统按照人类的价值观…

C++标准模板(STL)- 迭代器库 - 流迭代器- 写入 std::basic_ostream 的输出迭代器(二)

迭代器库-流迭代器 迭代器库提供了五种迭代器的定义&#xff0c;同时还提供了迭代器特征、适配器及相关的工具函数。 迭代器分类 迭代器共有五 (C17 前)六 (C17 起)种&#xff1a;遗留输入迭代器 (LegacyInputIterator) 、遗留输出迭代器 (LegacyOutputIterator) 、遗留向前迭代…

网络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…

WebSockets 完全指南:在 Postman 中测试实时通信

标题&#xff1a;WebSockets 完全指南&#xff1a;在 Postman 中测试实时通信 摘要 Postman 是 API 开发者广泛使用的工具&#xff0c;支持 RESTful API 的测试和调试。随着实时通信的兴起&#xff0c;WebSockets 协议变得日益重要。本文将详细介绍如何在 Postman 中测试 Web…

改进经验模态分解方法-通过迭代方式(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…

【python学习】bytearray 数组

在Python中&#xff0c;bytearray 是一个可变序列&#xff0c;用于表示一个字节数组。与不可变的 bytes 类型相比&#xff0c;bytearray 允许你修改其内容。你可以通过索引来访问和修改 bytearray 中的元素&#xff0c;也可以添加或删除元素。 使用 bytearray 的一些示例&…

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

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

740. 删除并获得点数(leetcode)

740. 删除并获得点数&#xff08;leetcode&#xff09; 题目描述 给你一个整数数组 nums &#xff0c;你可以对它进行一些操作。每次操作中&#xff0c;选择任意一个 nums[i] &#xff0c;删除它并获得 nums[i] 的点数。之后&#xff0c;你必须删除 所有 等于 nums[i] - 1 和 …

目标检测算法用一个案例详细讲解

学习目标&#xff1a; 目标检测算法用一个案例详细讲解 学习内容&#xff1a; 主要以YOLO为例 YOLO 工作流程 输入图像&#xff1a; 首先&#xff0c;输入一张图像&#xff0c;该图像将被调整为固定大小&#xff08;如 416x416&#xff09;。网格划分&#xff1a; 图像被划分…

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

文章目录 国际算法基础概念常见的加密算法及分类签名和验签基础概念常见的签名算法应用场景 国密算法对称加密&#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;评估与反馈的智能化⭐教学资源的优…

spring-boot-configuration-processor注释处理器

开源项目SDK&#xff1a;https://github.com/mingyang66/spring-parent 个人文档&#xff1a;https://mingyang66.github.io/raccoon-docs/#/ spring-boot-configuration-processor是springboot提供的一个注释处理器&#xff08;annotation processor&#xff09;,它用于在编译…

Python多线程Concurrent

背景 从 Python3.2 开始&#xff0c;标准库为我们提供了 concurrent.futures 模块&#xff0c;它提供了 ThreadPoolExecutor 和 ProcessPoolExecutor两个类&#xff0c;实现了对 threading 和 multiprocessing 的进一步抽象&#xff08;这里主要关注线程池&#xff09;&#x…

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;供玩家投币游玩。…