双指针:第130题 字符串最短循环子串 | 豆包MarsCode AI刷题

62 阅读3分钟

1. 问题描述

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

2. 问题背景

这个问题是字符串处理中的一个经典问题,它涉及到循环模式的识别,对于理解字符串操作和算法设计具有重要意义。

3. 概念解释

  • 子串:子串是指字符串中连续的一段字符序列。例如,在字符串 "hello" 中,"ell" 和 "o" 都是它的子串。
  • 循环子串:循环子串是指可以通过重复拼接自身得到原字符串的子串。例如,在字符串 "ababab" 中,"ab" 是一个循环子串,因为它重复三次可以得到原字符串。

4. 思路分析

解决这个问题的关键在于识别出构成整个字符串的最短循环子串。我们可以采取以下步骤:

  1. 遍历所有可能的子串长度:从1到字符串长度的一半,因为如果子串长度超过一半,它不可能通过重复拼接形成整个字符串。
  2. 检查能否整除:只有当子串长度能整除字符串长度时,才可能通过重复拼接形成整个字符串。
  3. 验证子串重复:对于每个可能的子串长度,检查通过重复该子串是否能得到原字符串。

5. 代码详解

首先,定义一个solution函数,它接受一个字符串inp作为参数,并返回最短循环子串或空字符串。

def solution(inp):
    n = len(inp)

接下来,遍历所有可能的子串长度,从1到字符串长度的一半。

    # 遍历所有可能的子串长度
    for i in range(1, n // 2 + 1):

对于每个子串长度,检查字符串长度是否能被该子串长度整除。如果能,继续检查。

        if n % i == 0:  # 只有当子串长度能整除字符串长度时才可能重复
            substring = inp[:i]

检查通过重复这个子串是否能得到原字符串。如果可以,返回这个子串。

            if substring * (n // i) == inp:  # 检查是否可以通过重复子串得到原字符串
                return substring

如果遍历完所有可能的子串长度后都没有找到循环子串,返回空字符串。

    return ""

6. 个人思考

在解决这个问题时,我首先考虑了效率问题。由于我们需要检查所有可能的子串长度,这可能导致算法的效率较低。因此,我限制了子串长度的范围,只检查到字符串长度的一半,因为超过一半的子串不可能通过重复拼接形成整个字符串。

此外,我也思考了代码的简洁性和可读性。通过将重复子串的检查封装在一个简单的if语句中,我使得代码更加直观易懂。同时,我也意识到这个问题的解决方案可能不是唯一的,因为不同的子串长度可能会导致相同的结果,但根据题目要求,我们只需要找到最短的循环子串。

最后,我认为这个问题是一个非常好的练习,它不仅帮助我们理解字符串操作,还锻炼了我们对算法效率的考量和优化能力。通过解决这个问题,我们能够更好地理解如何在实际编程中应用算法和数据结构。