LeetCode 28. 实现 strStr()
题目链接LeetCode 28.实现strStr()
KMP:
class Solution {
public:
void getNext(int *next, string &s)
{
int j = 0;
next[0] = j;
//初始化指针
for(int i = 1;i < s.size();i++)
{
while(j > 0 && s[i] != s[j])
{
j = next[j - 1];
}
//指针i与j所对应的字符不一致时,j回退
if(s[i] == s[j])
{
j++;
}
//指针i与就所对应的字符一致时,j向前移动
next[i] = j;
//更新next数组
}
}
//得到next数组,即前缀表,记录前缀末尾的字符位置(字符下标+1)与前缀长度。
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 && haystack[i] != needle[j])
{
j = next[j - 1];
}
//模板字符串与所给字符串字符不匹配时,将前缀表中j所在位置(下标)的值赋给j
if(haystack[i] == needle[j])
{
j++;
}
//匹配时,j前移。
if(j == needle.size())
{
return (i - needle.size() + 1);
}
//j达到模板字符串长度时,返回下标
}
return -1;
}
};
思路:利用前缀表(next数组)的方法,先找到模板串里的最长前缀与其所在位置,再通过前缀表来寻找到所给字符串中与模板串相匹配的字符的最小下标。
LeetCode 459.重复的子字符串
题目链接:LeetCode 459. 重复的子字符串
移动匹配:
class Solution {
public:
bool repeatedSubstringPattern(string s) {
string ss = s + s;
ss.erase(ss.begin());
ss.erase(ss.end() - 1);
if(ss.find(s) != std::string::npos)
return true;
return false;
}
};
思路:将两个s拼接成一个ss,若能从ss找到s则证明s是由重复子字符串构成。
小结:拼接以后要将ss的首字符与尾字符删除,否则一定能找到s。
KMP:
class Solution {
public:
void getNext(int *next,string &s)
{
int j = 0;
next[j] = 0;
for(int i = 1;i < s.size();i++)
{
while(j > 0 && s[i] != s[j])
{
j = next[j - 1];
}
if(s[i] == s[j])
{
j++;
}
next[i] = j;
}
}
bool repeatedSubstringPattern(string s) {
int next[s.size()];
getNext(next,s);
int len = s.size();
int n = len - next[len - 1];
if(next[len - 1] != 0 && len % n == 0)
return true;
return false;
}
};
思路:利用KMP法先得出最大前缀,之后再通过原字符减去最大前缀得到重复字符串(证明过程略)。若原字符对重复字符串取模为0,则原字符串为重复字符串否则不为重复字符串。