1. 题目来源
相关题目:
2. 题目解析
简单 dp 即可,注意读题,要求多个长度相同子串出现,返回原串较短的那个子串。那么就需要注意遍历顺序了,从长度较短的串开始遍历。
f[i][j]
表示 s1
以 i
结尾的子串,与 s2
以 j
结尾的子串的最大长度。那么以 s1[i]==s2[j]
作状态划分,成立则说明,f[i][j]=f[i-1][j-1]+1
不成立则自然以 i, j
结尾的子串长度为 0。
需要记录 f[i][j]
的最大值,状态更新位置为终点,可以推导得到最长子串的起点位置。
还有一种暴力匹配的方法,KMP 实现也可,find 也可。查看:[每日一题] 38. 查找两个字符串a,b中的最长公共子串(字符串、动态规划、LCS问题)。
时间复杂度:
O
(
n
m
)
O(nm)
O(nm)
空间复杂度:
O
(
n
m
)
O(nm)
O(nm)
#include <bits/stdc++.h>
using namespace std;
const int N = 1e3+5;
int n, m;
string s1, s2;
// int f[N][N];
int main() {
while (cin >> s1 >> s2) {
if (s1.size() > s2.size()) swap(s1, s2);
s1 = ' ' + s1, s2 = ' ' + s2;
n = s1.size(), m = s2.size();
vector<vector<int>> f(n, vector<int>(m, 0));
int start = -1, maxlen = -1;
for (int i = 1; i < n; i ++ )
for (int j = 1; j < m; j ++ ) {
if (s1[i] == s2[j])
f[i][j] = f[i - 1][j - 1] + 1;
if (f[i][j] > maxlen) {
maxlen = f[i][j];
start = i - maxlen + 1;
}
}
cout << s1.substr(start, maxlen) << endl;
}
return 0;
}
/*
msatgfqpleswalkvowbcjllbmtxdjqtxlxoyrobrnpuctrcowegmyjjmgkzibmbplpslbsfawrqmzeckiwctwizhpkthvqaukxmzhyqbhhjbihzoidheibsrfbzaruhlwoiwlexwoaicikadrhcvevcnwxwsskooedipgftdfcmdpdonvjtzsncuylrbfzstplfsnebivzdyhhbajfokqvscrzobdzgnfkeqfhzpugbekegaiidhervdsgc
kicndbvtazczllcipodvlrliqargjayiivkuymrusywvotxycdzscogyejpvfmrldueulwijytocrf
ki在较短串中先出现,vo后出现,所以要从短串开始遍历!
*/