首页 > 其他分享 >LeetCode 28题找出字符串中第一个匹配项的下标

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

时间:2024-06-23 22:31:32浏览次数:28  
标签:下标 int lps needle 28 len 匹配 haystack LeetCode


给你两个字符串 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 仅由小写英文字符组成

在我的回答中使用了kmp算法,可以极大的节省所用时间

class Solution {
public:
    int strStr(string haystack, string needle) {
        if (needle.empty()) return 0; // needle 为空,返回0

        // 构建部分匹配表
        vector<int> lps = computeLPS(needle);

        int i = 0, j = 0;
        while (i < haystack.size()) {
            if (haystack[i] == needle[j]) {
                ++i;
                ++j;
            }
            if (j == needle.size()) {
                return i - j; // 找到了完整匹配,返回起始位置
            } else if (i < haystack.size() && haystack[i] != needle[j]) {
                if (j != 0) {
                    j = lps[j - 1];
                } else {
                    ++i;
                }
            }
        }
        
        return -1; // 没有找到匹配
    }

private:
    vector<int> computeLPS(string needle) {
        int n = needle.size();
        vector<int> lps(n, 0);
        int len = 0; // 当前匹配的前缀的长度
        int i = 1;
        
        while (i < n) {
            if (needle[i] == needle[len]) {
                ++len;
                lps[i] = len;
                ++i;
            } else {
                if (len != 0) {
                    len = lps[len - 1];
                } else {
                    lps[i] = 0;
                    ++i;
                }
            }
        }
        
        return lps;
    }
};
  • strStr 方法

    • 先处理特殊情况,如果 needle 为空,则直接返回 0
    • 调用 computeLPS 方法计算 needle 的部分匹配表。
    • 使用双指针 ijhaystack 上进行匹配:
      • 如果当前字符匹配,则同时向后移动 ij
      • 如果 j 移动到 needle 的末尾,返回匹配起始位置 i - j
      • 如果当前字符不匹配,并且 j 不为 0,则根据部分匹配表调整 j
      • 如果 j 为 0,则移动 i 继续尝试匹配。
    • 如果循环结束仍未找到匹配,则返回 -1
  • computeLPS 方法

    • 构建 needle 的部分匹配表 lps
    • 使用 len 记录当前匹配的前缀的长度,i 表示当前字符。
    • 根据当前字符与前缀的匹配情况更新 lenlps[i]
    • 如果不匹配,根据 len 调整 len 的值。

总结

通过使用 KMP 算法,可以高效地在 haystack 中查找 needle 的第一个匹配项的位置,时间复杂度为 O(m + n),其中 m 是 haystack 的长度,n 是 needle 的长度。这种方法利用部分匹配表,在匹配过程中避免了回溯,使得算法效率得到了显著提升。

但是对于不熟悉kmp算法的人下面的一种方法更加简单

#include <string>

using namespace std;

class Solution {
public:
    int strStr(string haystack, string needle) {
        int hLen = haystack.length(); // 获取 haystack 的长度
        int nLen = needle.length();   // 获取 needle 的长度
        
        // 遍历 haystack,确保剩余长度足够容纳整个 needle
        for (int i = 0; i <= hLen - nLen; ++i) {
            int j = 0;
            // 逐个字符比较 needle 和 haystack 中的对应位置
            for (j = 0; j < nLen; ++j) {
                if (needle[j] != haystack[i + j]) // 不匹配时退出内循环
                    break;
            }
            
            if (j == nLen) // 如果 j 等于 needle 的长度,说明找到匹配
                return i; // 返回匹配起始位置
        }
        
        return -1; // 遍历完整个 haystack 后仍未找到匹配,返回 -1
    }
};

方法较为简单,但运行时间较长

标签:下标,int,lps,needle,28,len,匹配,haystack,LeetCode
From: https://blog.csdn.net/m0_61862494/article/details/139842068

相关文章

  • 力扣每日一题 美丽下标对的数目 枚举 哈希
    Problem:2748.美丽下标对的数目......
  • 基于二进制软件包 —安装 MySQL-8.0.28
    #!/bin/bash##********************************************************************#Author: Kevin#Date: 2024-06-23#FileName: install_mysql.sh#Description: Thetestscript#Copyright(C): 2024Allrightsreserved#****************************......
  • 【面试宝典】28道Java集合高频题库整理(附答案背诵版)
    常见的集合有哪些?常见的Java集合可以分为两大类:Collection和Map。Collection接口下主要有以下几种实现:List:有序的集合,其中的元素可以重复。ArrayList:基于动态数组实现,查询速度快,但在中间插入和删除元素时速度较慢。LinkedList:基于双向链表实现,插入和删除速......
  • Leetcode 225. 用队列实现栈 && 232.用栈实现队列(jvav)
    225.用队列实现栈    题目:请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。    本题可采用一个队列或两个队列完成,这里我使用一个队列实现栈,更加简洁,理解起来也不难。    栈的特点是先进后出,队......
  • Leetcode150.逆波兰表达式求值(Java)
    题目:        给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。请你计算该表达式。返回一个表示表达式值的整数。    栈的典型例题。题目要求为:求后缀表达式值。示例 1:输入:tokens=["2","1","+","3","*"]输出:9解释:该算式......
  • Day28.property使用part2
    1.property使用part2_多次调用类中的函数方法property用法,案例一代码如下:'''案例一'''classPeople:def__init__(self,name):self.__name=namedefget_name(self):returnself.__namedefset_name(self,val):......
  • LeetCode 209.长度最小的子数组
    链接209.长度最小的子数组-力扣(LeetCode)题目给定一个含有 n 个正整数的数组和一个正整数 target 。找出该数组中满足其总和大于等于 target 的长度最小的 子数组[numsl,numsl+1,...,numsr-1,numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。示......
  • Leetcode84 柱状图中最大的矩形
    题目描述给定n个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为1。求在该柱状图中,能够勾勒出来的矩形的最大面积解题思路思路一:暴力寻找,从每个位置出发,向左右两边扩散查找,若发现柱形比当前位置高,则宽度加一,组成长方形,代码实现如下,但是提交之后......
  • 价格减免(Lc2288)——模拟
    句子 是由若干个单词组成的字符串,单词之间用单个空格分隔,其中每个单词可以包含数字、小写字母、和美元符号 '$' 。如果单词的形式为美元符号后跟着一个非负实数,那么这个单词就表示一个 价格 。例如 "$100"、"$23" 和 "$6" 表示价格,而 "100"、"$" 和 "$1e5 不是。......
  • LeetCode 448. 找到所有数组中消失的数字(哈希表)
    448.找到所有数组中消失的数字思路:方法一,借助额外的0(n)空间sta进行哈希classSolution{public:vector<int>findDisappearedNumbers(vector<int>&nums){intn=nums.size();vector<int>sta(n,0);for(inti=0;i<n;i++){......