28. Implement strStr()*
https://leetcode.com/problems/implement-strstr/
题目描述
Implement strStr().
Return the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.
Example 1:
Input: haystack = "hello", needle = "ll"
Output: 2
Example 2:
Input: haystack = "aaaaa", needle = "bba"
Output: -1
Clarification:
What should we return when needle
is an empty string? This is a great question to ask during an interview.
For the purpose of this problem, we will return 0 when needle
is an empty string. This is consistent to C’s strstr() and Java’s indexOf().
C++ 实现 1
下面是遍历的方法. C++ 实现 2
采用 KMP 算法来实现.
class Solution {
public:
int strStr(string haystack, string needle) {
if (needle.empty()) return 0;
for (int i = 0; i < haystack.size(); ++ i) {
if (i + needle.size() > haystack.size()) break;
auto s = haystack.substr(i, needle.size());
if (s == needle) return i;
}
return -1;
}
};
C++ 实现 2
采用 KMP 算法来实现. KMP 算法常用于模式匹配/字符串查找. 下面代码我感觉虽然现在我能写出来, 可能过段时间就会忘记. KMP 算法的原理可以专门写一篇博客来介绍了, 这里尽力简要介绍一下…
(这个算法不是 “那么” 的好理解, 所以看不懂也没关系…, 多看书, 多查资料)
当我们知道 KMP 算法最后输出一个 n + 1
的 table 后, 我们可以用这个 table 来做这道题.
其中 needle
其实就是一个 pattern. 要在 haystack
查找这个 pattern, 我们首先利用 KMP 算法得到 needle
对应的 KMP table dp
, 然后, 判断 haystack[i]
是否等于 needle[j]
. 如果相等, 则考虑下一个字符.
如果不相等, 此时如果 j == 0
, 即 needle
中指针 j
已经退无可退了, 此时只需要移动指向 haystack
的指针 i
. 而如果 j != 0
, 那么 j = dp[j]
, 退回去.
使用 KMP 算法的好处是, i
只用前进, 无需后退. 在 C++ 实现 1
中, 由于使用了 substr
封装了细节, 我们看不出 i
有回退的现象.
使用 C++ 实现 1
中的代码, 最坏的情况时间复杂度可能达到
O
(
N
×
M
)
O(N\times M)
O(N×M),
比如:
haystack = "aaaaaaaaab"
needle = "aaaaab"
haystack
中第一轮比较从第一个 a
开始, 第二轮从第二个 a
开始. 但是使用 KMP 算法, 第一轮从第一个 a
开始, 第二轮从第 6 个 a
开始, 即不会发生回退的现象. 时间复杂度为
O
(
M
+
N
)
O(M + N)
O(M+N).
class Solution {
private:
vector<int> KMP(const string &str) {
vector<int> dp(str.size() + 1, 0);
int i = 1, j = 0;
while (i < str.size()) {
if (str[i] == str[j]) dp[++i] = ++j;
else if (j == 0) ++ i;
else j = dp[j];
}
return dp;
}
public:
int strStr(string haystack, string needle) {
if (needle.empty()) return 0;
auto dp = KMP(needle);
int i = 0, j = 0;
while (i < haystack.size()) {
if (needle[j] == haystack[i]) ++ j, ++i;
else {
if (j == 0) ++ i;
else j = dp[j];
}
if (j >= needle.size()) return i - needle.size();
}
return -1;
}
};