class Solution {
public:
void getNext(int* next, string& s) {
next[0] = 0; //next数组初始化
int j = 0; //前缀末尾
for (int i = 1; i < s.size(); i++) { //i为后缀末尾
while (j > 0 && s[i] != s[j]) {
j = next[j - 1]; //重点,遇到不相等的,就去找断点
}
if (s[i] == s[j]) {
j++;
}
next[i] = j;
}
}
int strStr(string haystack, string needle) {
if (needle.size() == 0) {
return 0;
}
int next[needle.size()];
getNext(next, needle);
int j = 0;
for (int i = 0; i < haystack.size(); i++) {
while (j > 0 && needle[j] != haystack[i]) {
j = next[j - 1];
}
if (needle[j] == haystack[i]) {
j++;
}
if (j == needle.size()) {
return i - needle.size() + 1;
}
}
return -1;
}
};
时间复杂度:O(N+M)
哎哎哎,彻底理解KMP对我现在来说还是有点小困难,先硬着头皮写点自己的见解。
知识点:前缀是指不包含最后一个字符的所有以第一个字符开头的连续子串。
后缀是指不包含第一个字符的所有以最后一个字符结尾的连续子串。
前缀表:起始位置到下标i之前(包括i)的子串中,有多大长度的相同前缀后缀。
思路:KMP算法首先最重要的是建立next数组,该过程就是建立前缀表,建立数组的时候呢,有三个主要步骤:(1)初始化next数组 (2)处理前后缀不相同的情况 (3)处理前后缀相同的情况
最主要的是处理不相同前后缀的情况,通过一个while循环进行判定,如果不相同,就让前缀末尾等于前缀末尾前一个元素的next值,这个next值代表的是需要从这个点开始与i进行比较。
其实最主要的点,就是在碰到不同元素的情况下找到needle数组的某个值继续往后比较,而不需要在needle数组的头重新开始比较,而这个值需要next数组才能找到。