Leetcode 28. 实现 strStr()
初见想法:使用两个for循环,暴力搜索,时间复杂度为O(n*m), 过于fuza
以下为KMP算法的实现:
class Solution {
public:
int strStr(string haystack, string needle) {
int next[needle.size()];
build_next(next, needle); // 构建next数组
int i = 0, j = 0; // 主串和子串的指针、
while (i < haystack.size())
{
if (haystack[i] == needle[j]) // 字符串匹配,指针后移
{
i++;
j++;
}
else if (j > 0) // 字符串匹配到中间停下来
{
j = next[j-1]; // j匹配失败回到上一个匹配成功的字符,再用next数组
}
else // j依然为0
{
i++;
}
if (j == needle.size()) return i - j;
}
return -1;
}
void build_next(int* next, const string& s)
{
next[0] = 0; // next数组第一个为0
int prefix_len = 0; // 当前共同前后缀指针
int i = 1; // next数组的指针
while (i < s.size())
{
if (s[i] == s[prefix_len])
{
prefix_len++;
next[i++] = prefix_len;
}
else
{
if (prefix_len == 0)
{
next[i++] = 0;
}
else
{
prefix_len = next[prefix_len-1];
}
}
}
}
};
重点为计算next数组,next数组代表着共同前后缀,就是在子串中可以跳过的个数
prefix_len = next[prefix_len-1], next数组索引从0开始,所以需要减1
459.重复的子字符串
初见想法:没想法
class Solution {
public:
bool repeatedSubstringPattern(string s) {
if (s.size() == 0) return false;
int next[s.size()];
build_next(next, s);
int len = s.size();
if (next[len-1] != 0 && len % (len - next[len-1]) == 0) return true;
return false;
}
void build_next(int* next, const string& s)
{
next[0] = 0;
int prefix_len = 0;
int i = 1;
while (i < s.size())
{
if (s[i] == s[prefix_len])
{
prefix_len++;
next[i++] = prefix_len;
}
else
{
if (prefix_len == 0)
{
next[i++] = 0;
}
else
{
prefix_len = next[prefix_len-1];
}
}
}
}
};
很复杂,使用kmp代码可以理解,但是证明过程有一点复杂。