给定一个非空的字符串,判断它是否可以由它的一个子串重复多次构成。给定的字符串只含有小写英文字母,并且长度不超过10000。
- 虽然是个简单题,但是很值得学习。
-
方法一:枚举法,该方法技巧很值得学习
- 假设字符串S = n*s 若s 长度 i ,当 j 指向一个元素时那么只需要对比:S[ j ] ?= S[ j-i ];
- i 从1 开始遍历,,当 i > strlen(s) / 2 时---->可以提前结束啦!(小优化)
- 还有一个小优化:若 N = strlen(s) , 则N%i 如果不等于0(n就是小数了),那么肯定不符合题意
bool repeatedSubstringPattern(char* s) {
int n = strlen(s);
for (int i = 1; i * 2 <= n; ++i) { //优化1
if (n % i == 0) { // 优化2
bool match = true;
for (int j = i; j < n; ++j) {
if (s[j] != s[j - i]) {
match = false;
break;
}
}
if (match) {
return true;
}
}
}
return false;
}
-
方法二:双字符串法
- S = n*x, 现构造新字符串 T=2S,即两个s相加
- 去掉 T 的开头与结尾两位,则这两处的子串被破坏掉,此时 T 中包含 2n-2 个子串。
- T 中包含2n-2个子串,S 中包含 n 个子串
- 若 T 中包含s,则有2n-2>=n,可得 n>=2。由此我们可知字符串 S 可由一个子串 x 重复至少2次构成,判定为true;
- 反之,若 T 中不包含 S,则有 2n-2<n,可得n<2,n只能为1,由此我们可知字符串 S=x,假定的子串就为 S 本身,判定为false。
bool repeatedSubstringPattern(string s) {
string str=s+s;
str=str.substr(1,str.size()-2);
if(str.find(s)==-1)
return false;
return true;
}
class Solution:
def repeatedSubstringPattern(self, s: str) -> bool:
return s in (s + s)[1:-1]
bool repeatedSubstringPattern(char* s) {
int n = strlen(s);
char k[2 * n + 1];
k[0] = 0;
strcat(k, s);
strcat(k, s);
return strstr(k + 1, s) - k != n;
说明:
- 以上内容仅是个人学习整理,内容来源:https://leetcode-cn.com/problems/repeated-substring-pattern/