给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。
示例 1:
输入: s = "abab" 输出: true 解释: 可由子串 "ab" 重复两次构成。 复制代码示例 2:
输入: s = "aba" 输出: false 复制代码示例 3:
输入: s = "abcabcabcabc" 输出: true 解释: 可由子串 "abc" 重复四次构成。 (或子串 "abcabc" 重复两次构成。) 复制代码提示:
- 1 <= s.length <= 10^4
- s 由小写英文字母组成
function repeatedSubstringPattern(s) {
const n = s.length;
for (let len = 1; len <= n / 2; len++) {
if (n % len !== 0) continue;
const pattern = s.slice(0, len);
let i = len;
while (i < n && s.slice(i, i + len) === pattern) {
i += len;
}
if (i === n) return true;
}
return false;
}
console.log(
"repeatedSubstringPattern('abcabcabcabc')",
repeatedSubstringPattern("abcabcabcabc")
); // repeatedSubstringPattern('abcabcabcabc') true
这个算法的时间复杂度是 ,因为它需要枚举所有可能的子串长度,并检查每个子串是否能够构成原始字符串。虽然它不是最优的算法,但是在输入规模比较小的情况下可以接受。
function repeatedSubstringPattern(s) {
return /^(\w+)\1+$/.test(s);
}
console.log(
"repeatedSubstringPattern('abcabcabcabc')=",
repeatedSubstringPattern("abcabcabcabc")
); // repeatedSubstringPattern('abcabcabcabc') true
这个实现方式使用了正则表达式来判断字符串是否可以由一个子串重复多次构成。如果字符串符合重复子串的规律,那么它一定可以匹配一个由子串和子串重复构成的正则表达式。其中 \1 表示引用前面的捕获分组,因此 (\w+)\1+ 表示由一个或多个子串和它们重复构成的字符串。
这个实现方式的时间复杂度和前面的实现方式一样,是 ,但是它的代码长度更短,可读性也更差。