题目链接:28. 实现 strStr()
题目:
实现 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
示例 3:
输入:haystack = “”, needle = “”
输出:0
提示:
- 1 <= haystack.length, needle.length <= 104
- haystack 和 needle 仅由小写英文字符组成
思路和算法:
这题使用KMP算法,KMP的经典思想就是:当出现字符串不匹配时,可以记录一部分之前已经匹配的文本内容,利用这些信息避免从头再去做匹配。关于KMP算法的主要讲解,看看卡哥的随想录——关于KMP算法讲解,或者卡哥的B站视频讲解。
代码(c++):
//使用KMP算法
//前缀表统一减一
class Solution {
public:
//构建next数组(前缀表)
void getNext(vector<int>& next, string& s) {
int j = -1; //j指向前缀末尾
next[0] = j; //next[i]表示i(包括i)之前最长相等前后缀长度(其实就是j)
for (int i = 1; i < s.size(); ++i) { //i指向后缀末尾,注意i从1开始
while (j >= 0 && s[i] != s[j + 1]) { //前后缀不同
j = next[j]; //向前回退
}
if (s[i] == s[j + 1]) { //前后缀相同
j++;
}
next[i] = j; //将j(前缀的长度)赋给next[i]
}
}
int strStr(string haystack, string needle) {
if (!needle.size()) return 0; //模式字符串为空,返回0
vector<int> next(needle.size()); //定义next数组
getNext(next, needle);
int j = -1; //因为next数组里记录的起始位置为-1
for (int i = 0; i < haystack.size(); ++i) { //遍历文本字符串haystack,注意i从0开始
while (j >= 0 && haystack[i] != needle[j + 1]) { //不匹配
j = next[j]; //j寻找之前匹配的位置
}
if (haystack[i] == needle[j + 1]) { //匹配,j和i同时向后移动
j++; //i的增加在for循环里
}
if (j == needle.size() - 1) { //文本字符串haystack里出现了模式串needle
return (i - needle.size() + 1);
}
}
return -1;
}
};
这里我是第一次接触KMP算法,还不是很了解,照着卡哥的代码捋了下来,下次碰着有个印象能写出来一点就好,再三遇这题一定能自己写出来!