459.重复的子字符串
解题关键:
当一个字符串由重复子串组成的,最长相等前后缀不包含的子串就是最小重复子串。
关键就是对上面结论的证明。最后在判断剩余的这个最小重复子串的长度和字符串s的长度是否成倍数关系,不成倍数关系就代表整个字符串不是由重复的子字符串构成的。
论证就不具体展开了,参考相关博文:代码随想录 (programmercarl.com)
class Solution {
public boolean repeatedSubstringPattern(String s) {
if(s.length() == 0) return false;
// 计算出next数组
int[] next = new int[s.length()];
int j = 0;
next[0] = 0;
for(int i = 1; i < s.length(); i++){
while(j > 0 && s.charAt(i) != s.charAt(j)){
j = next[j - 1];
}
if(s.charAt(i) == s.charAt(j)){
j++;
}
next[i] = j;
}
// 根据next数组的最后一位的值判断是否有重复的子字符串
if(next[s.length() - 1] > 0 && s.length() % (s.length() - next[s.length() - 1]) == 0){
return true;
}
return false;
}
}
方法2:移动匹配实现
关键点:
还是要先验证结论:将两个相同的字符串拼接在一起,如果在这个长字符串的中间能够组成一个新的拼接前的字符串,则代表这个字符串是由重复子字符串构成的。
论证就不具体展开了,参考相关博文:代码随想录 (programmercarl.com)
class Solution {
public boolean repeatedSubstringPattern(String s) {
// 这种解法的关键就是拼接两个s,然后判断这个字符串中间还会不会出现拼接出来的s
// 出现了就代表由重复子字符串构成,没出现就代表非重复子字符串构成
StringBuilder ssb = new StringBuilder(s).append(s);
String ss = ssb.substring(1, ssb.length() - 1).toString();
// 掐头去尾
// 还是得计算next数组
int[] next = new int[s.length()];
int j = 0;
next[0] = 0;
for(int i = 1; i < next.length; i++){
while(j > 0 && s.charAt(i) != s.charAt(j)){
j = next[j - 1];
}
if(s.charAt(i) == s.charAt(j)){
j++;
}
next[i] = j;
}
// 根据next数组进行判断
j = 0;
for(int i = 0; i < ss.length(); i++){
while(j > 0 && ss.charAt(i) != s.charAt(j)){
j = next[j - 1];
}
if(ss.charAt(i) == s.charAt(j)){
j++;
}
if(j == s.length()){
return true;
}
}
return false;
}
}