459.重复的子字符串
题目:459. 重复的子字符串
// //暴力解法超时O(N^2),需要剪枝操作
class Solution {
public:
bool isrepeat(string& s, string& son){
for(int j = 0; j < s.size(); j += son.size()){
int k = 0;
while(k < son.size()){
if(s[j+k] != son[k]) return false;
++k;
}
}
return true;
}
bool repeatedSubstringPattern(string s) {
for(int i = 1; i <= s.size() / 2; ++i){ //只需要循环主串的一半位置
//i是子串的结束位置
string son = s.substr(0,i);
//cout << son << endl;
if(isrepeat(s,son)) return true;
}
return false;
}
};
//移动匹配O(n)
//如果是由重复子串组成的,主串长度减去最长相等前后缀长度,就是重复子串长度
class Solution {
public:
bool repeatedSubstringPattern(string s) {
//如果符合要求,s+s一定包含s
string ss = (s + s).substr(1,s.size() * 2 - 2);
//string ss = s + s;
//ss.erase(ss.begin());ss.erase(ss.end() - 1);//这样删除也可以O(n)
if(ss.find(s) != string::npos) return true;//O(n)
else return false;
}
};
//KMP
class Solution {
public:
void getNext(int *next, string &s){
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) {
//if(s.size(() == 0) return false;
int next[s.size()];
getNext(next,s);
int son_len = s.size() - next[s.size() - 1];
if(next[s.size() - 1] != 0 && s.size() % son_len == 0) return true;
return false;
}
};
总结
字符串:反转,双指针,KMP找子串
双指针法展现出效率的优势:通过两个指针在一个for循环下完成两个for循环的工作