问题描述
小M在研究字符串时发现了一个有趣的现象:某些字符串是由一个较短的子串反复拼接而成的。如果能够找到这个最短的子串,便可以很好地还原字符串的结构。你的任务是给定一个字符串,判断它是否是由某个子串反复拼接而成的。如果是,输出该最短的子串;否则,输出空字符串""。
例如:当输入字符串为 abababab 时,它可以由子串 ab 反复拼接而成,因此输出 ab;而如果输入 ab,则该字符串不能通过子串的重复拼接得到,因此输出空字符串。
测试样例
样例1:
输入:
inp = "abcabcabcabc"
输出:'abc'
样例2:
输入:
inp = "aaa"
输出:'a'
样例3:
输入:
inp = "abababab"
输出:'ab'
样例4:
输入:
inp = "ab"
输出:''
问题理解
如果一个字符串可以由某个子串重复拼接而成,那么这个子串就是要找的最短循环子串。如果找不到这样的子串,则返回空字符串。
算法步骤
- 长度判断:首先,检查字符串的长度。如果字符串长度为1,直接返回空字符串,因为单个字符无法通过重复拼接得到。
- 子串生成:从长度为1的子串开始,逐步增加子串的长度,直到子串的长度达到字符串长度的一半。
- 子串验证:对于每个可能的子串,检查它是否可以通过重复拼接得到原始字符串。
- 返回结果:如果找到这样的子串,返回该子串;否则,返回空字符串。
具体步骤
- 遍历子串长度:从1到字符串长度的一半。
- 生成子串:对于每个长度,生成对应的子串。
- 拼接验证:将子串重复拼接,直到拼接后的字符串长度不小于原始字符串。
- 比较:如果拼接后的字符串与原始字符串相同,则该子串就是最短循环子串。
std::string solution(const std::string &inp) {
// 获取字符串的长度
int n = inp.length();
// 如果字符串长度为1,直接返回空字符串
if (n == 1) {
return "";
}
// 遍历可能的子串长度
for (int len = 1; len <= n / 2; ++len) {
// 检查当前子串长度是否能整除字符串长度
if (n % len == 0) {
// 获取当前子串
std::string sub = inp.substr(0, len);
// 构建通过重复子串得到的字符串
std::string repeated;
for (int i = 0; i < n / len; ++i) {
repeated += sub;
}
// 检查构建的字符串是否与原始字符串相同
if (repeated == inp) {
return sub; // 找到最短循环子串
}
}
}
// 如果没有找到符合条件的子串,返回空字符串
return "";
}
关键步骤解释
- 获取字符串长度:使用
inp.length()获取字符串的长度。 - 特殊情况处理:如果字符串长度为1,直接返回空字符串。
- 遍历可能的子串长度:从1到字符串长度的一半进行遍历。
- 检查子串长度是否能整除字符串长度:使用
n % len == 0判断。 - 获取当前子串:使用
inp.substr(0, len)获取当前子串。 - 构建通过重复子串得到的字符串:使用循环将子串重复拼接。
- 比较构建的字符串与原始字符串:如果相同,返回当前子串。
- 返回空字符串:如果没有找到符合条件的子串,返回空字符串。