题目链接
题目描述
实现 strStr()
函数。
给你两个字符串 haystack
和 needle
,请你在 haystack
字符串中找出 needle
字符串出现的第一个位置(下标从 0 开始)。如果不存在,则返回 -1
。
说明:
当 needle
是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。
对于本题而言,当 needle
是空字符串时我们应当返回 0 。这与 C 语言的 strstr() 以及 Java 的 indexOf() 定义相符。
示例 1:
输入:haystack = "hello", needle = "ll"
输出:2
示例 2:
输入:haystack = "aaaaa", needle = "bba"
输出:-1
提示:
1 <= haystack.length, needle.length <= 104
haystack
和needle
仅由小写英文字符组成
解题思路
法1:滑动窗口
- 窗口大小为
needle
的长度 - 首先找到首字母相同的位置,然后判断窗口内的字符是不是一样的
- 如果不一样,则继续寻找下一个首字母相同的位置,继续判断,直到
haystack
遍历到haystack.length() - neddle.length() + 1
的位置 - 这种方式最容易想到,但是在面对很长的字符串匹配时耗时太多,时间复杂度为
O(m * n)
法2:KMP
这个讲解过程参见代码随想录
AC代码
滑动窗口法
class Solution {
public int strStr(String haystack, String needle) {
int len1 = haystack.length();
int len2 = needle.length();
int slow = 0;
int fast = 0;
if (len2 == 0) {
return 0;
}
if (len1 < len2) {
return -1;
}
while (slow < len1 - len2 + 1) {
//找到首字母相等
while (slow < len1 && haystack.charAt(slow) != needle.charAt(fast)) {
slow++;
}
//没有找到首字母相等的
if (slow == len1) {
return -1;
}
//遍历后续字符,判断是否相等
while (slow < len1 && fast < len2 && haystack.charAt(slow) == needle.charAt(fast)) {
slow++;
fast++;
}
//如果找到
if (fast == len2) {
return slow - fast;
} else {
//如果没有找到
slow -= fast - 1;
fast = 0;
}
}
return -1;
}
}
KMP法
class Solution {
public int strStr(String haystack, String needle) {
int[] next = new int[needle.length()];
getNext(needle, next);
int i = 0;
int j = 0;
for (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 static void getNext(String s, int[] next) {
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(i) == s.charAt(j)) {
j++;
}
next[i] = j;
}
}
}