实现strStr()
一般的字符串匹配问题我们可以使用KMP算法来处理,当我们搜索文本串和模式串是否匹配的时候,我们先得到模式串的一个前缀表,其中前缀表中存放的内容是模式串的最长相等前后缀。例如文本串为:aabaabaafa,模式串为:aabaaf,那么文本串的前缀表就是010120。当我们开始搜索时,我们发现在模式串f字符不匹配,我们就f前缀表中前一个字符的前缀表中的数值,发现是2,那么我们就跳到模式串下标为2的字符,继续遍历字符串。对于aabaaf来说,在f处不匹配,就是最长相等后缀aa后面的一个字符f不匹配,那么我就可以跳到最长相等前缀aa后面的一个字符b来重新进行匹配,此时前缀表中记录的最长相等前后缀的长度就是这个字符串b的下标。我们首先需要先得到这个前缀表。
class Solution {
public:
//得到模式串needle的前缀表
void getNext(int* next,string& s)
{
int j = 0;//用j来表示最长前缀,但是同时j也表示最长前后缀的值
next[0] = j;
for(int i = 1;i < s.size();i++)//用i来表示最长后缀
{
while(j > 0 && s[i] != s[j])//前缀、后缀不相等的情况
{
j = next[j - 1];
}
if(s[i] == s[j])//前缀、后缀相等的情况
{
j++;
}
next[i] = j;//前后缀相等时,更新next[i]为j++的数值;不相等时,更新为next[i]为回退后的数组
}
}
int strStr(string haystack, string needle) //haystack是文本串,needle是模式串
{
int next[needle.size()];//创建一个数组用来存放前缀表的内容
getNext(next,needle);//得到前缀表
int j = 0;
for(int i = 0;i < haystack.size();i++)//用i来遍历文本串
{
while(j > 0 && haystack[i] != needle[j])
{
j = next[j - 1];//j回退到j-1所对应的下标处
}
if(haystack[i] == needle[j])
{
j++;
}
if(j == needle.size())
{
return (i - needle.size() + 1);
}
}
return -1;
}
};
重复的子字符
这道题的思路有两种,第一个思路就是用两个字符串s相加,结果就是s+s,当我们去掉最前面一个和最后面一个得到的字符串中能查询到字符串s,那就说明这个字符串由重复子串构成。这种思想称为移动匹配。实现这种思路我们需要调用库函数,因为库函数的内部实现原本就比较高,所以使用这种想法的时间复杂度比较高。
class Solution {
public:
bool repeatedSubstringPattern(string s) {
string t = s + s;
t.erase(t.begin()); t.erase(t.end() - 1); // 掐头去尾
if (t.find(s) != std::string::npos) return true; // r
return false;
}
};
其中,对于t.find(s) != std::string::npos,npos可以表示string的结束位置,意思就是说如果在字符串t中找不到字符串s,就会返回nops。这是npos的一个用法。文章来源:https://www.toymoban.com/news/detail-613877.html
这道题的另一种解法就是KMP算法。这里直接给出结论,数组长度剪去最长相等前后缀的长度就是第一个周期的长度,如果这个的长度可以被整除,那就说明整个数组是这个周期的循环。文章来源地址https://www.toymoban.com/news/detail-613877.html
class Solution {
public:
//得到前缀表
void getNext(string& s,int* next)
{
int j = 0;//最长前缀
next[0] = 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(s,next);
int len = s.size();
if(next[len-1] != 0 && len % (len - (next[len - 1]))== 0)
{
return true;
}
return false;
}
};
到了这里,关于代码随想录day9|实现strStr()、重复的子字符串的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!