解题思路:动态规划
首先使用二维dp,令dp[i][j]表示s1的前i个字符构成的字符串和s2的前j个字符构成的字符串的最长公共子序列。
那么有状态转移方程:
当s1[i] == s2[j]时,dp[i + 1][j + 1] = dp[i][j] + 1;否则 dp[i + 1][j + 1] = max ( dp[i][j + 1], dp[i + 1][j] )
时间复杂度O(mn),空间复杂度O(mn)。
空间压缩,dp数组由二维压缩到一维
注意到动态转移方程中的 i+1只和 i 有关,因此可以将dp数组压缩到一维。
注意到题目要求的空间复杂度为 O(min(m, n)),我们强制令n >= m,如果 n < m 则交换m和n,交换s1和s2。
这样开的dp数组长度为m + 1最小,符合O(min(m, n))。
下面给出完整代码。
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n, m;
string s1, s2;
cin >> n >> m;
if(n < m) {
cin >> s2 >> s1;
swap(m, n);
} else {
cin >> s1 >> s2;
}
vector<int> dp(m + 1, 0);
for(int i = 0; i < n; ++i) {
int lastDp = 0; //表示上一项,即二维的dp[i][j],初始为dp[i][0] = 0
for(int j = 0; j < m; ++j) {
int tmp = dp[j + 1]; //临时记录当前项,即二维的dp[i][j+1]
if(s1[i] == s2[j]) {
dp[j + 1] = lastDp + 1; //即dp[i+1][j+1] = dp[i][j] + 1
} else {
dp[j + 1] = max(dp[j + 1], dp[j]); //即dp[i+1][j+1]=max(dp[i][j+1], dp[i+1][j])
}
lastDp = tmp; //更新上一项为之前临时记录的
}
}
cout << dp[m];
}
// 64 位输出请用 printf("%lld")



京公网安备 11010502036488号