字符串最短循环子串 | 豆包MarsCode AI 刷题

49 阅读4分钟

问题描述

小M在研究字符串时发现了一个有趣的现象:某些字符串是由一个较短的子串反复拼接而成的。如果能够找到这个最短的子串,便可以很好地还原字符串的结构。你的任务是给定一个字符串,判断它是否是由某个子串反复拼接而成的。如果是,输出该最短的子串;否则,输出空字符串""

例如:当输入字符串为 abababab 时,它可以由子串 ab 反复拼接而成,因此输出 ab;而如果输入 ab,则该字符串不能通过子串的重复拼接得到,因此输出空字符串。

思路

  1. 理解问题:我们需要找到一个子串,这个子串可以重复拼接直到构成整个字符串。这种字符串通常被称为“由重复子串组成的字符串”。

  2. 如何判断一个字符串是否可以由某个子串重复拼接而成

    • 如果一个字符串 inp 能够由某个子串 s 重复拼接,那么字符串的长度应该是子串长度的整数倍。
    • 比如,abcabcabcabc 就是由 abc 这个子串重复拼接而成的。我们可以通过检查不同长度的子串来验证这一点。
  3. 解题步骤

    • 从长度为1的子串开始,逐步检查每个可能的子串,直到字符串长度的一半为止(因为超过一半长度的子串再重复也无法覆盖整个字符串)。
    • 对于每个子串,检查它是否可以通过重复拼接成原字符串。如果可以,就返回该子串;如果不行,则继续检查下一个子串。
    • 如果最终没有找到合适的子串,就返回空字符串。
  4. 优化点:我们只需要检查长度从1到 len(inp)//2 的子串,因为任何长度大于一半的子串都不可能重复拼接成一个长度为 n 的字符串。

解题思考

假设输入的字符串 inp 长度为 n,我们可以枚举所有可能的子串长度 length,从1开始,直到 n//2。对于每个 length,我们检查该子串能否重复拼接得到 inp。如果能,就返回该子串;如果遍历完所有子串都找不到符合条件的,就返回空字符串。

代码详解

def solution(inp):
    # 遍历可能的子串长度,从1到 len(inp)//2
    for length in range(1, len(inp) // 2 + 1):
        # 如果原字符串的长度能被当前子串长度整除
        if len(inp) % length == 0:
            # 获取当前长度的子串
            substring = inp[:length]
            # 通过重复子串构建一个新的字符串
            repeated_string = substring * (len(inp) // length)
            # 比较构建的字符串与原字符串是否相同
            if repeated_string == inp:
                return substring
    # 如果没有找到符合条件的子串,返回空字符串
    return ""

if __name__ == "__main__":
    print(solution("abcabcabcabc") == "abc")
    print(solution("aaa") == "a")
    print(solution("abababab") == "ab")
    print(solution("ab") == "")
    print(solution("abcdabcdabcdabcd") == "abcd")
    print(solution("b") == "")

代码解析

  1. 循环遍历子串长度:从1到 len(inp)//2,我们逐一尝试不同长度的子串。对于每个长度,首先检查它能否整除原字符串的长度。如果不能整除,说明这个长度的子串不能组成原字符串,因此跳过。

  2. 构建重复的字符串:如果当前的子串长度能整除字符串的长度,我们就用当前子串重复拼接,看看能否构成原字符串。

  3. 返回结果:如果找到了符合条件的子串,直接返回它;如果没有找到,最终返回空字符串。

详解

以字符串 abcabcabcabc 为例,长度为 12,我们从长度为 16 的子串进行尝试。

  • 长度1a,构造的字符串是 a 重复 12 次,显然不对。
  • 长度2ab,构造的字符串是 ab 重复 6 次,结果是 abababababab,不对。
  • 长度3abc,构造的字符串是 abc 重复 4 次,结果是 abcabcabcabc,与原字符串一致,返回 abc

总结

  1. 从小到大检查子串的有效性:我们从可能的最短子串开始,逐步检查,直到找到第一个符合条件的子串,这样可以尽早退出,避免无效计算。
  2. 字串拼接的核心原理:这个题目本质上是在考察如何通过字符串的重复结构来还原其组成。
  3. 时间复杂度:最坏情况下,我们会遍历所有长度从 1n//2 的子串,这样的时间复杂度大约是 O(n^2),因为每次构建重复的字符串需要 O(n) 的时间。