1. 简介

在本教程中,我们将展示如何在 Java 中判断一个字符串是否是由某个子串重复构成的。

2. 问题定义

我们先明确一些前提条件:

  • 字符串长度至少为2
  • 子串至少重复一次

举个例子:

✅ 以下字符串满足条件:

"aa"
"ababab"
"barrybarrybarry"

❌ 以下字符串不满足条件:

"aba"
"cbacbac"
"carlosxcarlosy"

我们将通过几种不同方式来解决这个问题。

3. 简单粗暴的实现(暴力解法)

思路如下:

  • 遍历字符串前半部分字符,构建可能的子串
  • 每次尝试用当前子串替换原字符串中的所有匹配项
  • 如果替换后字符串为空,说明原字符串完全由该子串构成

示例代码如下:

public static boolean containsOnlySubstrings(String string) {
    if (string.length() < 2) {
        return false;
    }

    StringBuilder substr = new StringBuilder();
    for (int i = 0; i < string.length() / 2; i++) {
        substr.append(string.charAt(i));

        String clearedFromSubstrings = string.replaceAll(substr.toString(), "");

        if (clearedFromSubstrings.length() == 0) {
            return true;
        }
    }

    return false;
}

✅ 测试用例:

String validString = "aa";
String validStringTwo = "ababab";
String validStringThree = "baeldungbaeldung";

String invalidString = "aca";
String invalidStringTwo = "ababa";
String invalidStringThree = "baeldungnonrepeatedbaeldung";

✅ 验证代码:

assertTrue(containsOnlySubstrings(validString));
assertTrue(containsOnlySubstrings(validStringTwo));
assertTrue(containsOnlySubstrings(validStringThree));

assertFalse(containsOnlySubstrings(invalidString));
assertFalse(containsOnlySubstrings(invalidStringTwo));
assertFalse(containsOnlySubstrings(invalidStringThree));

⚠️ 踩坑提醒:
这个方法虽然逻辑简单,但性能较差,因为 replaceAll 在每次循环中都会执行一次正则匹配,整体时间复杂度为 O(n²),不建议用于长字符串。

4. 高效解法(巧妙解法)

我们换个思路:
如果一个字符串是由某个子串重复构成的,那么它一定是其自身的某种“旋转”。

比如 "ababab""ab" 的重复拼接,也可以看作是 "ab" 的多次旋转拼接。

有个定理可以帮我们简化判断:

如果字符串 A 和 B 长度相同,那么 A 是 B 的旋转字符串当且仅当 A 是 B+B 的子串

所以我们只需要判断原字符串是否出现在 (string + string).substring(1, ...) 中即可。

✅ 实现代码如下:

public static boolean containsOnlySubstringsEfficient(String string) {
    return ((string + string).indexOf(string, 1) != string.length());
}

✅ 用法和测试方式与前面一致,但这次时间复杂度降到了 O(n),性能更优。

💡 小贴士:
这个技巧在字符串算法中很经典,常用于判断重复结构,比如在 LeetCode 上也有类似题目。

5. 总结

我们介绍了两种判断字符串是否由重复子串构成的方法:

方法 时间复杂度 说明
暴力解法 O(n²) 思路简单,适合短字符串
高效解法 O(n) 利用字符串旋转定理,效率更高,推荐使用

所有示例代码均可在 GitHub 仓库 中找到。


原始标题:Checking If a String Is a Repeated Substring