字符串最短循环子串
一、问题重现
问题描述
小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"
输出:''
二、解题思路
算法思路
-
问题理解:
- 给定一个字符串
inp,我们需要判断它是否可以由某个子串重复拼接而成。 - 如果可以,返回最短的重复子串;否则,返回空字符串
""。
- 给定一个字符串
-
数据结构选择:
- 使用字符串切片和循环来处理字符串。
-
算法步骤:
-
从字符串的第一个字符开始,尝试找到一个子串,使得该子串可以重复拼接成原字符串。
-
对于每个可能的子串长度
end,检查以下条件:- 子串的第一个字符与当前字符相同。
- 原字符串的长度是子串长度的整数倍。
-
如果满足上述条件,进一步检查该子串是否可以重复拼接成原字符串。
-
如果找到这样的子串,返回该子串;否则,继续尝试下一个可能的子串长度。
-
如果所有可能的子串长度都不满足条件,返回空字符串
""。
-
算法实现
-
外层循环:
for end in range(1, len(inp) // 2 + 1):尝试所有可能的子串长度,从 1 到len(inp) // 2。- 这是因为如果子串长度大于
len(inp) // 2,那么它不可能重复拼接成原字符串。
-
条件检查:
if inp[end] == inp[begin] and len(inp) % end == 0:检查子串的第一个字符是否与当前字符相同,并且原字符串的长度是否是子串长度的整数倍。
-
内层循环:
start = [i * end for i in range(num)]:生成子串的起始位置列表。for i in range(end)和for j in range(1, num):检查子串是否可以重复拼接成原字符串。
-
返回结果:
- 如果找到满足条件的子串,返回该子串;否则,返回空字符串
""。
- 如果找到满足条件的子串,返回该子串;否则,返回空字符串
三、代码实现
def solution(inp: str) -> str:
# Edit your code here
begin = 0
for end in range(1, len(inp) // 2 + 1):
if inp[end] == inp[begin] and len(inp) % end == 0:
num = len(inp) // end
start = [i * end for i in range(num)]
flag = False
for i in range(end):
for j in range(1, num):
if inp[start[j - 1] + i] != inp[start[j] + i]:
flag = True
break
if flag:
break
if not flag:
return inp[begin:end]
return ""
四、算法复杂度
-
时间复杂度:
- 外层循环最多执行
len(inp) // 2次。 - 内层循环最多执行
end * num次,其中num = len(inp) // end。 - 因此,最坏情况下,时间复杂度为
O(n^2),其中n是字符串的长度。
- 外层循环最多执行
-
空间复杂度: 主要的空间开销是
start列表,其长度为num,最多为n // 2。因此,空间复杂度为O(n)。