题目:
给定一个非空的字符串,判断它是否可以由它的一个子串重复多次构成。给定的字符串只含有小写英文字母,并且长度不超过10000。
示例 1:
输入: "abab"
输出: True
解释: 可由子字符串 "ab" 重复两次构成。
示例 2:
输入: "aba"
输出: False
示例 3:
输入: "abcabcabcabc"
输出: True
解释: 可由子字符串 "abc" 重复四次构成。 (或者子字符串 "abcabc" 重复两次构成。)
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/repeated-substring-pattern
链接:https://leetcode-cn.com/problems/repeated-substring-pattern
法1:周期性
1 1 /*周期串为s,那么设定t表示周期,那么剩下的就是依次对每个t值进行遍历看是否真的满足周期为t,数学中周期的表达式是f(x+t)==f(x),那么代码中可以这样写s[i%t]==s[i]*/ 2 2 3 3 class Solution { 4 4 public boolean repeatedSubstringPattern(String s) { 5 5 //如果真的具有周期性,t>=1,t <= s.length/2 6 6 if(s == null) return false; 7 7 for(int t = 1; t <= s.length()/2; t++){ //为所有可能的周期长度,即题目中的子串长度 8 8 if(s.length() % t != 0) continue; //s如果具有周期性,它和子串在长度上成倍数关系,直接减少一些判断 9 9 int i = t; 10 10 while( i < s.length() && s.charAt(i % t) == s.charAt(i)){ //判断是否满足f(x+t)==f(x) 11 11 i++; 12 12 } 13 13 if(i == s.length()) return true; 14 14 } 15 15 return false; 16 16 17 17 } 18 18 }
法2:split()活用
split(String str) 的一般情况:
特殊情况:
如果字符串与输入的任何一部分都不匹配,得到的字符串数组将只有一个元素,即这个字符串。
如果输入的是字符串的周期性子串,得到的字符串数组长度为0。
1 // 法二:活用split() 2 // 如果字符串存在周期性,那么以该子串分割字符串得到的字符串数组应该长度为0 3 //不能忽视这里隐含的条件:字符串的长度是子串的整数倍(筛选,减少时间) 4 class Solution { 5 public boolean repeatedSubstringPattern(String s) { 6 if(s == null) return false; 7 for(int t = s.length()-1; t > 0; i--){ //t为子串长度 8 if(s.length() % t != 0) continue; 9 if(s.split(s.substring(0,t)).length == 0) return true; 10 } 11 return false; 12 } 13 }
法3:
拼接该字符串,截去首尾各一个字符,如果仍然包含该字符串则包含重复的子字符串(具有周期性)。只截一个是为了判断重复子串长度为1的情况。当重复子串长度大于1时,任意截去首尾小于等于重复子字符串长度都可
1 class Solution { 2 public boolean repeatedSubstringPattern(String s) { 3 String str = s+s; 4 str = str.substring(1,str.length()-1); 5 return str.contains(s); 6 } 7 }