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

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

题目描述

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

难度

简单

题目链接

点击在LeetCode中查看题目

示例

示例 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算法

KMP算法是一种高效的字符串匹配算法,它通过预处理模式串来避免不必要的比较。

关键点:

  1. 构建next数组(部分匹配表)
  2. 利用已匹配信息加速匹配过程
  3. 避免不必要的回溯

具体步骤:

  1. 构建模式串的next数组
  2. 利用next数组进行匹配:
    • 主串指针i不回溯
    • 模式串指针j根据next数组移动
  3. 找到匹配或遍历完主串

时间复杂度:O(m + n)
空间复杂度:O(n),用于存储next数组

图解思路

KMP匹配过程示意图

步骤 主串位置 模式串位置 是否匹配 下一步操作
1 s[0] p[0] 不匹配 移动模式串
2 s[1] p[0] 匹配 同时右移
3 s[2] p[1] 匹配 同时右移
4 s[3] p[2] 不匹配 查next数组

Next数组构建过程

索引i 前缀集合 后缀集合 next[i]
0 - - -1
1 s[0] s[0] 0
2 s[0:1] s[1:2] 0
3 s[0:2] s[1:3] 1

代码实现

public class Solution {
    public int StrStr(string haystack, string needle) {
        if (string.IsNullOrEmpty(needle)) return 0;
        if (haystack.Length < needle.Length) return -1;
    
        // 构建next数组
        int[] next = BuildNext(needle);
    
        // KMP匹配过程
        int i = 0, j = 0;
        while (i < haystack.Length && j < needle.Length) {
            if (j == -1 || haystack[i] == needle[j]) {
                i++;
                j++;
            } else {
                j = next[j];
            }
        }
    
        return j == needle.Length ? i - j : -1;
    }
  
    private int[] BuildNext(string pattern) {
        int[] next = new int[pattern.Length];
        next[0] = -1;
        int i = 0, j = -1;
    
        while (i < pattern.Length - 1) {
            if (j == -1 || pattern[i] == pattern[j]) {
                i++;
                j++;
                next[i] = j;
            } else {
                j = next[j];
            }
        }
    
        return next;
    }
}

执行结果

  • 执行用时:64 ms
  • 内存消耗:36.9 MB

代码亮点

  1. 🎯 使用KMP算法实现高效字符串匹配
  2. 💡 巧妙构建next数组优化匹配过程
  3. 🔍 利用已匹配信息避免重复比较
  4. 🎨 代码结构清晰,变量命名规范

常见错误分析

  1. 🚫 没有正确处理边界情况
  2. 🚫 next数组构建错误
  3. 🚫 匹配过程中指针移动错误
  4. 🚫 返回值计算错误

解法对比

解法 时间复杂度 空间复杂度 优点 缺点
暴力匹配 O(m*n) O(1) 实现简单 效率低
KMP算法 O(m+n) O(n) 效率高 实现复杂
Sunday算法 O(m*n) O(1) 实现简单 最坏情况效率低

相关题目

posted @   旧厂街小江  阅读(0)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示