题目
对于给定的两个字符串 s 和 t,你需要找出它们的最长公共子串。特别地,如果存在多个答案,输出在较短串中最先出现的那个。
子串为从原字符串中,连续的选择一段字符(可以全选、可以不选)得到的新字符串。
如果字符串 a 的一个子串 a′ 与字符串 b 的一个子串 b′ 完全相等,那么子串 a′,b′ 是字符串 a,b 的一个公共子串。
示例
输入:
awaabb aawbb输出:aa
说明:在这个样例中,"aa" 和 "bb" 都是 s 和 t 的最长公共子串,但 "aa" 在较短串 s 中首先出现,因此输出 "aa"。
分析
枚举较短字符串的所有可能子串,并按长度从长到短的顺序在较长字符串中查找是否存在,从而找到最长公共子串。
代码解释
findLongestCommonSubstring
函数:
从较短字符串的最大长度开始,依次递减长度,尝试截取子串。
对于每个截取的子串,使用 string::find
方法在较长字符串中查找。
如果找到该子串且其长度大于当前记录的最长长度,更新最长长度和最长子串。
一旦找到最长子串,提前结束循环。
时间复杂度:O(),
是较短字符串的长度,
是较长字符串的长度,
是子串长度
空间复杂度:O()
#include <iostream>
#include <string>
using namespace std;
// 查找最长公共子串的函数
void findLongestCommonSubstring(const string& shorter, const string& longer) {
int maxLength = 0;
string longestSubstring;
// 遍历较短字符串的所有可能子串长度
for (int len = shorter.length(); len >= 1; --len) {
// 遍历较短字符串,以当前长度截取子串
for (int start = 0; start + len <= shorter.length(); ++start) {
string sub = shorter.substr(start, len);
// 在较长字符串中查找该子串
size_t found = longer.find(sub);
if (found != string::npos) {
// 若找到且长度大于当前最长长度,更新最长子串信息
if (len > maxLength) {
maxLength = len;
longestSubstring = sub;
break;
}
}
}
// 如果已经找到最长子串,提前结束循环
if (maxLength > 0) {
break;
}
}
cout << longestSubstring << endl;
}
int main() {
string s, t;
getline(cin, s);
getline(cin, t);
// 确定较短和较长的字符串
if (s.size() < t.size()) {
findLongestCommonSubstring(s, t);
} else {
findLongestCommonSubstring(t, s);
}
return 0;
}