Leetcode的AC指南 —— 字符串/KMP:28.找出字符串中第一个匹配项的下标

摘要:
Leetcode的AC指南 —— 字符串/KMP:28.找出字符串中第一个匹配项的下标。题目介绍:给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。

文章目录

  • 一、题目
  • 二、解析(go)
    • 1、一个简单的AC方法
    • 2、KMP算法:直接使用前缀表作为next数组
  • 三、其他语言版本
    • Java
    • C++
    • Python

一、题目


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

力扣题目链接

示例 1:

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

示例 2:

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

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

二、解析(go)


1、一个简单的AC方法

思路:让needle在haystack中滑动

go:

func strStr(haystack string, needle string) int {runes := []byte(haystack)for i := 0; i <= len(haystack)-len(needle); i++ {if string(runes[i:len(needle)+i]) == needle {return i}}return -1}
  • 时间复杂度O(n-m)
  • 空间复杂度O(n)

2、KMP算法:直接使用前缀表作为next数组

思路:

  • 构造next数组

    1. 初始化:前缀末尾指针before指向第一个字符,第一个子串的前后缀长度next[0]为0
    2. 默认before指针之前的字符与behind指针之前的字符相等。
    3. 比较before指向的字符与behind指向的字符是否相等。
      • 当不相同时,before指向前一个字符,重新比较,直到before指向第一个字符或者before与behind的字符相等时,结束比较。
      • 当又相同时,before指向下一个字符。
    4. before的位置就是最长前后缀长度,更新next数组。
  • 使用next数组做匹配

    • 初始化
      • i为文本串起始位置,j为模式串起始位置
      • 得到next数组
    • 在文本串中查找模式串,对比i和j分别对应的字符
      • 若i和j相等,则i和j同时后移
      • 若i和j不相等,则j寻找之前匹配的位置,
        • 也就是通过next数组的最大相同子串长度滑动j,确定从模式串的哪个位置开始重新比较
      • 当 j 比完模式串的最后一个字符后,说明模式串在文本串中出现过,返回结果
      • 若文本串遍历结束,j也没有指向模式串的最后一个字符,就返回-1
//直接将前缀表作为next数组
func getnext(next []int, s string) {// before: 前缀末尾,前缀长度// behand:后缀末尾before := 0next[0] = 0for behind := 1; behind < len(s); behind++ {for before > 0 && s[behind] != s[before] { // 前缀与后缀不相等before = next[befor-1]}if s[behind] == s[before] { // 前缀与后缀相等before++}next[behind] = before}
}
// 直接将前缀表作为next数组的匹配实现
func strStr(haystack string, needle string) int {j := 0 // j 为模式串的起始位置, next数组记录的起始位置为0next := make([]int, len(needle))getnext(next, needle)for i := 0; i < len(haystack); i++ { // i从0开始for j > 0 && haystack[i] != needle[j] { // 不匹配j = next[j-1] // j寻找之前匹配的位置}if haystack[i] == needle[j] { // 匹配,j 和 i同时向后移动j++ // i的增加在for循环中}if j == len(needle) { // 文本串haystack中出现了模式串needlereturn i - j + 1}}return -1
}
  • n为文本串长度,m为模式串长度。
  • 匹配的过程是O(n),
  • 单独生成next数组,时间复杂度是O(m)。
  • 整个KMP算法的时间复杂度是O(n+m)的。

三、其他语言版本


Java

class Solution {//前缀表(不减一)Java实现public int strStr(String haystack, String needle) {if (needle.length() == 0) return 0;int[] next = new int[needle.length()];getNext(next, needle);int j = 0;for (int i = 0; i < haystack.length(); i++) {while (j > 0 && needle.charAt(j) != haystack.charAt(i)) j = next[j - 1];if (needle.charAt(j) == haystack.charAt(i)) j++;if (j == needle.length()) return i - needle.length() + 1;}return -1;}private void getNext(int[] next, String s) {int j = 0;next[0] = 0;for (int i = 1; i < s.length(); i++) {while (j > 0 && s.charAt(j) != s.charAt(i)) j = next[j - 1];if (s.charAt(j) == s.charAt(i)) j++;next[i] = j; }}
}

C++

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

Python


class Solution:def getNext(self, next: List[int], s: str) -> None:j = 0next[0] = 0for i in range(1, len(s)):while j > 0 and s[i] != s[j]:j = next[j - 1]if s[i] == s[j]:j += 1next[i] = jdef strStr(self, haystack: str, needle: str) -> int:if len(needle) == 0:return 0next = [0] * len(needle)self.getNext(next, needle)j = 0for i in range(len(haystack)):while j > 0 and haystack[i] != needle[j]:j = next[j - 1]if haystack[i] == needle[j]:j += 1if j == len(needle):return i - len(needle) + 1return -1

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

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

相关文章

前端angular 实现验证码 输入+展示(大框+加粗内容 )

参考用原生方在手机上此效果 如何实现一个4位验证码输入框效果 输入使用的任旧是html的input元素&#xff0c;只是让它看不到了只是把输入到input元素里的内容取到的内容放在改过样式的div里不需要dom操作&#xff0c;直接用双向绑定就拿到数据&#xff1b;使用动态样式 设置了…

sublime代码对齐设置

sublime代码对齐设置 sublime代码对齐设置待续、更新中 sublime代码对齐设置 Preferences->Key Bindings->user->编辑⽂档输⼊: { "keys": ["ctrlaltl"], "command": "reindent" }然后选中你要对齐的代码块或者ctrla全选代…

从0开始python学习-46.pytest框架之通过yaml处理接口关联问题-针对变量处理

目录 1. 提取变量 1.1 提取方法 1.2 提取地方&#xff1a;响应的body&#xff0c;响应的cookie&#xff0c;响应头 1.3 提取方式&#xff1a; 1.4 示例&#xff1a;在能获取到对应token的yaml用例中写入 2.使用变量&#xff1a;封装一个通用extract_util.py 3. 调用测试用…

卸载流氓软件联软

这个流氓软件也是在更新的&#xff0c;下面是本人在联想邵阳笔记本下卸载流程&#xff0c;非常简单 注&#xff1a;按照本文卸载之后&#xff0c;我重新装了一次这个垃圾&#xff0c;但是发现重装完之后&#xff0c;系统启动之后就会进入黑屏&#xff0c;也就是说&#xff0c;…

【数据库基础】Mysql与Redis的区别

看到一篇不错的关于“Mysql与Redis的区别”的文章&#xff0c;转过来记录下~ 文章目录 一、数据库类型二、运行机制三、什么是缓存数据库呢&#xff1f;四、优缺点比较五、区别总结六、数据可以全部直接用Redis储存吗&#xff1f;参考资料 一、数据库类型 Redis&#xff1a;NOS…

Win10安装配置Redis,修改密码

一、下载Redis tporadowski 提供了 支持 Windows平台的 Redis 安装包&#xff0c;目前仍在维护&#xff0c;目前最新版本是 5.0.14&#xff0c;更新速度跟Redis官网也相差好几个大版本。 下载地址&#xff1a;https://github.com/tporadowski/redis/releases 二、Redis 安装 …

Java面向对象基础

面向对象 1&#xff09;优点 易维护、易复用、易扩展&#xff0c;由于面向对象有封装、继承、多态的特性&#xff0c;可以设计出低耦合的系统&#xff0c;使系统更加灵活&#xff0c;更加易于维护。 2&#xff09;缺点 性能比面向过程低。因为类在调用时需要实例化&#xff0c…

Golang学习之路一六运算符

Golang学习之路一六运算符 算数运算符 符号说明相加-相减*相乘/相除%求余自增–自减 package mainimport "fmt"func main() {a : 10b : 6// fmt.Println(ab)// -fmt.Println(a-b)// *fmt.Println(a*b)// /fmt.Println(a/b)// %fmt.Println(a%b)// fmt.Println(a)a…

哈希-力扣202快乐数

题目 编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」 定义为&#xff1a; 对于一个正整数&#xff0c;每一次将该数替换为它每个位置上的数字的平方和。然后重复这个过程直到这个数变为 1&#xff0c;也可能是 无限循环 但始终变不到 1。如果这个过程 结果为 1&…

Spring AOP(详解)

目录 1.AOP概述 2.AOP相关术语 3.Spring AOP的原理机制 3.1JDK动态代理 3.2 CGLIB动态代理 3.3简单代码展示 3.3.1JDK动态代理 3.3.2CGLIB动态代理 4.Spring的AOP配置 4.1pom.xml 4.2增强方法 4.3切点 4.4切面 5.基于注解的AOP配置 5.1.创建工程 5.2.增强 5.3AOP…

React 基础

文章目录 React是什么?1. JSX 简介1.1 在 JSX 中嵌入表达式1.2 JSX 中指定属性1.3 使用 JSX 指定子元素1.4 JSX 表示对象 2. 元素渲染2.1 将一个元素渲染为 DOM 3. 组件 & Props3.1 函数组件与class组件3.1.1 函数组件3.1.2 class组件3.2 渲染组件 & props 3.1 Props的…

Windows 环境多个JDK安装与切换

一、下载jdk 去Oracle官网上下载想要安装的jdk版本&#xff0c;https://www.oracle.com/java/technologies/downloads/。 二、安装jdk 双击.exe文件&#xff0c;选择好安装目录进行安装。多个版本的jdk重复这两步操作就好。 三、多版本的jdk都下载安装完成之后&#xff0…

串口基本知识

概述&#xff1a; RS232适用于短距离通信&#xff0c;RS485适用于长距离的多点通信&#xff0c;而RS422适用于中长距离的高速通信。选择适合的串口标准应根据具体应用场景的需求来进行。 RS232的优缺点 RS-232采取不平衡传输方式&#xff0c;即所谓单端通讯。RS-232是为点对…

docker部署firefox浏览器,实现远程访问

拉取firefox镜像&#xff0c;部署代码 docker run -d --name firefox -e TZAsia/Hong_Kong -e DISPLAY_WIDTH1920 -e DISPLAY_HEIGHT1080 -e KEEP_APP_RUNNING1 -e ENABLE_CJK_FONT1 -e VNC_PASSWORD12345678ABCabc -p 5800:5800 -p 5900:5900 -v /docker/firefox/config:/…

构建免费的Dokan和WooCommerce构建线上课程市场在线销售数字课程

我们知道创建良好的学习说明和材料很困难。但当涉及到销售时&#xff0c;就变得更加困难。如果您无法出售您的课程&#xff0c;那么没有什么比这更令人沮丧的了。 幸运的是&#xff0c;如果您使用的是 WordPress 网站&#xff0c;那么您可以非常轻松且免费地完成此操作。借助L…

React使用Valtio的hook实现响应式状态管理

Valtio 是一个轻量级的库&#xff0c;可以在前端应用程序中管理状态。它的使用方式非常简单直观&#xff0c;让我们能够轻松跟踪和更新应用程序的状态&#xff0c;并且无需手动处理组件重新渲染的逻辑。假设我们正在构建一个社交媒体应用&#xff0c;我们想要追踪用户的信息、主…

Wargames与bash知识12

Wargames与bash知识12 Bandit20 关卡提示&#xff1a; 主目录中有一个setuid二进制文件&#xff0c;它执行以下操作&#xff1a;它在您指定为命令行参数的端口上连接到localhost。然后&#xff0c;它从连接中读取一行文本&#xff0c;并将其与前一级别的密码&#xff08;band…

【Angular教程 230106】03 Angular事件、表单事件、事件对象、双向数据绑定

Angular教程 230106#快捷 04 Angular事件、表单事件、事件对象、双向数据绑定&#xff08;45分&#xff09; 0 一些基础的概念 1 执行事件 (click)”getData()” 执行事件 angular 在 Angular 中&#xff0c;“执行事件”通常指的是当一个特定的事件发生时触发的一系列动作…

web学习笔记(十三)

目录 1.for循环 1.1格式&#xff1a; 1.2执行步骤&#xff1a; 1.3补充&#xff1a; 2. while循环和do-while循环 2.1格式&#xff1a; 补充断点调试&#xff1a; 补充穷举法&#xff1a; 1.for循环 1.1格式&#xff1a; for(变量初始化&#xff1b;判断条件&#xff1…

L1-005 考试座位号(Java)

题目 每个 PAT 考生在参加考试时都会被分配两个座位号&#xff0c;一个是试机座位&#xff0c;一个是考试座位。正常情况下&#xff0c;考生在入场时先得到试机座位号码&#xff0c;入座进入试机状态后&#xff0c;系统会显示该考生的考试座位号码&#xff0c;考试时考生需要换…