kmp算法:(还是没理解太懂,但是差不多)
例子:aabaaf
010120
i代表后缀末尾,j代表前缀末尾和j++是最大回文串的长度(str[j++]之前的都相同)
例如:str=aab,最大回文串长度1,前缀aa,后缀ab时,str[1]之前的都相同,从str【1】开始比较,及a和b比较(描述的不好,下次看也不知道还能不能看懂)
例如:aabaaf,看 i 指向 f 时,看aabaa的最大回文串长度(此时 j =1, j++=2),下标2指向b与f比较
i从1开始一直循环size()-1次
一次循环需要和前后缀不同的情况,考虑前后缀相同的情况(得到next数组的值)
void getNext(int* next, const string& s) {
int j = 0;
next[0] = 0;
for(int i = 1; i < s.size(); i++) {
// 前后缀不相同了
while (j > 0 && s[i] != s[j]) { // j要保证大于0,因为下面有取j-1作为数组下标的操作
j = next[j - 1]; // 注意这里,是要找前一位的对应的回退位置了
}
if (s[i] == s[j]) {// 找到相同的前后缀
j++;
}
next[i] = j;
}
}
求next数组的过程,相当于用整体的匹配规则(自己用自己的next数组)匹配前缀和后缀。上面代码的回退j=next[j-1]和整体匹配的时候 j 回到对应的next数组的位置操作一样。
整体匹配如下:
int strStr(string haystack, string needle) {
if (needle.size() == 0) {
return 0;
}
vector<int> next(needle.size());
getNext(&next[0], needle);
int j = 0;
for (int i = 0; i < haystack.size(); i++) {
while(j > 0 && haystack[i] != needle[j]) {//与求next数组逻辑相同
j = next[j - 1];
}
if (haystack[i] == needle[j]) {
j++;
}
if (j == needle.size() ) {
return (i - needle.size() + 1);
}
}
return -1;
}