(9/60)实现strStr()、重复的子字符串
实现strStr
暴力遍历法
思路
双层循环,第一层遍历原字符串,第二层同时遍历寻找的字符串,一旦不匹配时,第一层退回到起始字符的下一位重新开始遍历。
复杂度分析
时间复杂度:最差时O(N^M)。最差情况每个寻找字符到最后一个字符不匹配,操作次数为原字符串长度N*寻找字符长度M。
空间复杂度:O(1)。
注意点
略
代码实现
class Solution {
public:
int strStr(string haystack, string needle) {
int p1 = 0;
int p2 = 0;
int index = -1;
while(p1 < haystack.size()){
if(haystack[p1] == needle[p2]){
index = p1; // 记录下标
while(p2 < needle.size()){
if(haystack[p1++] != needle[p2++]){
p2 = 0;
p1 = index; // 因为后面p1会++,取到index就可以了
index = -1;
break;
}
}
}
p1++; // 注意这里
}
return index;
}
};
KMP算法
思路
算法思想是利用字符串最大公共前后缀(我觉得叫最大“周期”前后缀更易理解,强调是从左到右的匹配相等),来减少重复比对。
在操作上,核心就是“不匹配,j回退”(while(j > 0 && s[j] != s[i]) j = next[j - 1];),而i不回退,一直后移。(i对应haystack或needle,j对应needle)。
- 获取neddle的next数组。
- 遍历haystack,needle不匹配就j回退。
- 遍历到字符串末尾就结束。
复杂度分析
时间复杂度:O(N+M)。
- 获取
next数组的复杂度为 O(n),其中 n 是模式串的长度。 - 在主循环中,需要遍历主串 haystack 的每个字符,时间复杂度为 O(m),其中 m 是主串 haystack 的长度。
- 对于每个字符,进行最多 j 次比较,其中 j 是当前匹配的字符数。在最坏情况下,j 最大为模式串 needle 的长度,因此最多进行 O(n) 次比较。
综上所述,整个算法的时间复杂度为 O(m + n),其中 m 是主串 haystack 的长度,n 是模式串 needle 的长度。空间复杂度为 O(n),用于存储 next 数组。
空间复杂度:O(N)。模式串长度N的前缀表。
注意点
略
代码实现
class Solution {
public:
// KMP算法
// 获取next数组
vector<int> getNext(string& s){
vector<int> next(s.size(),0);
// 初始化
next[0] = 0;
int j = 0;
for(int i = 1;i < s.size() && j < s.size();i++){
// 不匹配,j回退
while(j > 0 && s[j] != s[i]){
j = next[j - 1];
}
// 匹配
if(s[j] == s[i]) j++;
// next赋值
next[i] = j;
}
return next;
}
int strStr(string haystack, string needle) {
vector<int> next = getNext(needle);
int j = 0;
// =size的时候说明末端匹配了,i、j都到了.end()位置
// 进入循环直接触发if返回下标。
for(int i = 0;i <= haystack.size();i++){
if(j >= needle.size())
return i - needle.size();
// 不匹配,j回退
while(j > 0 && haystack[i] != needle[j]){
j = next[j - 1];
}
// 匹配
if(haystack[i] == needle[j]) j++;
}
return -1;
}
};
重复的子字符串
leetcode:459. 重复的子字符串
暂时跳过!

浙公网安备 33010602011771号