题目:找出字符串中第一个匹配项的下标
给你两个字符串 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 。
提示:
haystack和needle仅由小写英文字符组成
解题思路
去除字符串中不包括目标串以及目标串是空串和两个串相等的情况,剩下的就是遍历haystack,比较第i位与needle的第一位是否相同,并且haystack的i+needle.length-1处与needle串的最后一个字符相等,则进入子循环遍历之间每一位是否相同
- 要初始化前缀表,记下每一段的最长相等前后缀长度,存入next数组,其实该长度值真正的表示是:最长相等前缀末尾+1元素的下标
- 定义左右指针,右指针递增
- 如果左右字符不相等,则回退到相等的情况,没有相等就回到p的开始
- 相等则最长相等前后缀长度增加,左指针负责增加,右指针负责记录
- 文本串s和模式串p匹配
- 定义两个指针i,j分别在两字符串中游走
- 当匹配失败时,p通过next数组进行回退到匹配相等的情况
- 否则,逐个匹配,增加匹配长度,一直到完全匹配成功
- 完全匹配不了,返回-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;
}
运行结果
复杂度分析
- 空间复杂度:O(n)
- 时间复杂度:O(n)
在掘金(JUEJIN) 一起分享知识, Keep Learning!