字符串最短循环子串(第100道)
题目链接
https://www.marscode.cn/practice/8eeee14o2vr7vn?problem_no=100
题目描述
# 问题描述
- 输入一个字符串,判断其是否完全循环,若是循环的,输出最短的循环子串,否则输出空`""`
- 如输入 `abababab`,输出 `ab`;输入 `ab` 则输出 `""`
## 输入格式
- 合法字符串 如 `abcabcabcabc` `aaa`
## 输出格式
- 最短的循环子串 `"abc"` `"a"`
## 输入样例
- `"abcabcabcabc"`
## 输出样例
- `"abc"`
## 数据范围
测试数据集
题目思路
这道题我的思路十分暴力简单,如果大家有什么其他更好的方法也可以分享给我。
首先,如果字符串时空串或者只有一个字符,就不存在什么循环之说,直接返回空串或原字符就行了。
如果字符串不为空串,考虑到题目求的是循环子串,那原字符串最少也是由一个子串循环两次构成的,所以我们找子串的时候,只需要从原字符串的前半部分找就行了。
接下来就很简单了,用一个for循环一次截取字符串,得到一个模版串,判断这个模版串是否符合要求就行了,因为题目要求最短,所以我们找到的第一个符合要求的模版串就是答案。
接下来的重点就是如何判断这个模版串是否符合要求,是不是我们想要的模版串。
第一步,先判断原字符串的长度是否能整除模版串的长度,如果不能的话,这个模版串肯定不可能是循环子串了,可以直接跳过。
第二步,从原字符串中依次截取和模版串相同长度的子串,判断子串是否和模版串相等,若截取至原字符串末尾,所有子串都与模版串相等,那这个模版串就是我们要的最短循环子串了。如果出现一个不等,则不是。重新截取模版串重复上述操作。
题目答案
public class No100 {
public static void main(String[] args) {
// Add your test cases here
System.out.println(solution("abcabcabcabc").equals("abc"));
//false
System.out.println(solution("abababab").equals("abc"));
//false
System.out.println(solution("ab").equals("abc"));
//true
System.out.println(solution("abababab").equals("ab"));
}
public static String solution(String inp) {
// Edit your code here
//空串直接返回
if(inp.length() <= 0){
return "";
}
if (inp.length() == 1){
return inp;
}
//输入串的长度
int inpL = inp.length();
//结果
String result = "";
for(int i = 1;i< inpL / 2;i++){
//依次截取字符串
result = inp.substring(0,i);
//获取临时模式串的长度
int tempL = result.length();
//判断是否整除,不整除一定不是完全循环
if (inpL % tempL != 0) {
continue;
}
//标识是否是因为完全循环而退出
boolean flag = true;
//每次截取与模式串相同的长度进行匹配
for(int start = tempL;start <= inpL -tempL;start += tempL ){
//若出现任何一次不匹配,直接退出
if (!inp.substring(start, start+tempL).equals(result)) {
flag = false;
break;
}
}
//找到答案
if (flag) {
return result;
}
}
return "";
}
}
总结感受
这道题难度不大,很多人看一眼就有想法,也很容易就能做出来,但是想和做有时候确实可能会有点不一样。想法是个大概的思路,做却需要落实到具体细节,忽略一个细节都可能做错。
我做这道题的最大感受就是细节决定成败,还有想和做有一定的区别。一开始我的想法是这不就是一道KMP,还特地去重新学了一下KMP,但是真正做这道题的时候发现压根就不需要KMP,直接暴力做就行了。