夯实算法-找出字符串中第一个匹配项的下标

272 阅读2分钟

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

给你两个字符串 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<=1041 <= haystack.length, needle.length <= 10^4
  • haystack 和 needle 仅由小写英文字符组成

解题思路

去除字符串中不包括目标串以及目标串是空串和两个串相等的情况,剩下的就是遍历haystack,比较第i位与needle的第一位是否相同,并且haystack的i+needle.length-1处与needle串的最后一个字符相等,则进入子循环遍历之间每一位是否相同

  1. 要初始化前缀表,记下每一段的最长相等前后缀长度,存入next数组,其实该长度值真正的表示是:最长相等前缀末尾+1元素的下标
    • 定义左右指针,右指针递增
    • 如果左右字符不相等,则回退到相等的情况,没有相等就回到p的开始
    • 相等则最长相等前后缀长度增加,左指针负责增加,右指针负责记录
  2. 文本串s和模式串p匹配
    • 定义两个指针i,j分别在两字符串中游走
    • 当匹配失败时,p通过next数组进行回退到匹配相等的情况
    • 否则,逐个匹配,增加匹配长度,一直到完全匹配成功
  3. 完全匹配不了,返回-1

代码实现

public int strStr(String haystack, String needle) {
    int len = needle.length();
    if (len == 0) return 0;
    char[] s = haystack.toCharArray();
    char[] p = needle.toCharArray();
    int[] next = new int[len];
    // next 初始化
    for (int left = 0, right = 1; right < len; right++) { //right go forward
        //left 回退
        while (left > 0 && p[left] != p[right]) {
            left = next[left - 1];
        }
        //匹配长度增加
        if (p[left] == p[right]) {
            left++;
        }
        next[right] = left;
    }

    for (int i = 0, j = 0; i < s.length; i++) { //s go forward
        //p回退
        while (j > 0 && s[i] != p[j]) {
            j = next[j - 1];
        }
        //匹配长度增加
        if (s[i] == p[j]) {
            j++;
        }
        //完全匹配
        if (j == len) return i - len + 1;
    }
    return -1;

}

运行结果

Snipaste_2023-05-04_21-48-47.png

复杂度分析

  • 空间复杂度:O(n)
  • 时间复杂度:O(n)

掘金(JUEJIN) 一起分享知识, Keep Learning!