题目描述
小M在研究字符串时发现了一个有趣的现象:某些字符串是由一个较短的子串反复拼接而成的。如果能够找到这个最短的子串,便可以很好地还原字符串的结构。你的任务是给定一个字符串,判断它是否是由某个子串反复拼接而成的。如果是,输出该最短的子串;否则,输出空字符串""。
例如:当输入字符串为 abababab 时,它可以由子串 ab 反复拼接而成,因此输出 ab;而如果输入 ab,则该字符串不能通过子串的重复拼接得到,因此输出空字符串。
测试样例
样例1
输入:inp = "abcabcabcabc"
输出:'abc'
样例2
输入:inp = "aaa"
输出:'a'
样例3
输入:inp = "abababab"
输出:'ab'
样例4
输入:inp = "ab"
输出:''
样例5
输入:inp = "abcdabcdabcdabcd"
输出:'abcd'
样例6
输入:inp = "b"
输出:''
思路
- 长度限制:如果一个字符串
s的长度为n,那么它的重复子串的长度len必须是n的一个因子。也就是说,len的取值范围是从1到n/2。 - 构造与比较:对于每一个可能的子串长度
len,我们可以提取出字符串的前len个字符作为候选子串,然后构造一个新的字符串,通过重复这个子串n / len次来验证是否能够还原出原字符串。 - 效率考虑:由于我们只需要检查到
n/2的长度,因此在最坏情况下,我们的算法复杂度为 O(n^2),但在实际情况中,由于字符串比较和构造的效率,通常会更快。
Java代码
public class Main {
public static String solution(String inp) {
// Edit your code here
int n = inp.length();
for (int len = 1; len <= n / 2; len++) {
if (n % len == 0) {
String substring = inp.substring(0, len);
StringBuilder sb = new StringBuilder();
for (int j = 0; j < n / len; j++) {
sb.append(substring);
}
if (sb.toString().equals(inp)) {
return substring;
}
}
}
return "";
}
public static void main(String[] args) {
// Add your test cases here
System.out.println(solution("abcabcabcabc").equals("abc"));
}
}
复杂度分析
时间复杂度:
- 外层循环的最大迭代次数为
n/2,即O(n)。 - 内层循环的拼接操作在最坏情况下需要执行
n/len次,每次拼接的时间复杂度为O(len),因此内层循环的时间复杂度为O(n). - 因此,整体时间复杂度为
O(n^2),在最坏情况下(例如字符串为aaaa...),需要检查所有可能的子串长度。
空间复杂度:整体空间复杂度为 O(n)。