28. 实现 strStr()
//暴力解法
class Solution {
public:
int strStr(string haystack, string needle) {
if(haystack == needle || needle.size() == 0) return 0;
if(needle.size() > haystack.size()) return -1;
for(int i = 0; i < haystack.size(); ++i){
int res = 0;
int j = 0;
while(i < haystack.size() && haystack[i] == needle[j]){
res++;
i++;
j++;
}
if(res == needle.size()) return i - res;
else i -= res;
}
return -1;
}
};
KMP算法
KMP的经典思想就是:当出现字符串不匹配时,可以记录一部分之前已经匹配的文本内容,利用这些信息避免从头再去做匹配。
最重要的就是求next数组(前缀表:最长相等前后缀的长度 )
//求next数组
void getNext(int *next const string& s){
//i是后缀末尾,j是前缀末尾(j同时代表最大公共前后缀长度)
//(1)初始化
int j = 0; // 前缀最开始指向下标0
next[0] = 0; //一个字母的最大前后缀长度为0
for(int i = 1; i < next.size(); ++i){
//(2)处理前后缀不相等 前缀回退,回退到上一个不相等位置,也就是next[j - 1]
while(j > 0 && next[i] != next[j]){
j = next[j - 1];
}
//(3)处理前后缀相等 前缀后移
if(next[i] == next[j]){
j++;
}
//(4)给next数组赋值
next[i] == j;
}
}
//KMP
class Solution {
public:
void getNext(int *next , const string& s){
//i是后缀末尾,j是前缀末尾(j同时代表最大公共前后缀长度)
//(1)初始化
int j = 0; // 前缀最开始指向下标0
next[0] = 0; //一个字母的最大前后缀长度为0
for(int i = 1; i < s.size(); ++i){
//(2)处理前后缀不相等 前缀回退,回退到上一个不相等位置,也就是next[j - 1]
while(j > 0 && s[i] != s[j]){
j = next[j - 1];
}
//(3)处理前后缀相等 前缀后移
if(s[i] == s[j]){
j++;
}
//(4)给next数组赋值
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; //needle的下标
for(int i = 0; i < haystack.size(); ++i){
while(j > 0 && haystack[i] != needle[j]){
j = next[j - 1];
}
if(haystack[i] == needle[j]){
j++;
}
if(j == needle.size()) return i - j + 1;
}
return -1;
}
};
帮你把KMP算法学个通透!(理论篇)_哔哩哔哩_bilibili