leetcode1143:最长公共子序列

题目链接

leetcode

题目描述

给定两个字符串 text1text2,返回这两个字符串的最长 公共子序列 的长度。如果不存在,返回 0
一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下,删除某些字符(也可以不删除任何字符)后组成的新字符串。
例如,"ace""abcde" 的子序列,但 "aec" 不是 "abcde" 的子序列。
两个字符串的 公共子序列 是这两个字符串所共同拥有的子序列。

C++ 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// 1143. 最长公共子序列
// 高频面试题 - CodeTop

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

/*
状态表示:
f[i][j] 表示 text1[...i] 和 text2[...j] 最长公共子序列的长度。
状态计算:
a[i] != b[j]:
f[i][j] = max(f[i-1][j], f[i][j-1])
a[i] == b[j]:
f[i][j] = f[i-1][j-1] + 1
初始化:
f[0][j] = 0,其中 i = 0, 0 <= j <= n
f[i][0] = 0,其中 j = 0, 0 <= i <= n

时间复杂度:O(mn)
其中 m 和 n 分别是两个字符串的长度。
空间复杂度:O(mn)
*/
class Solution {
public:
int longestCommonSubsequence(string text1, string text2) {
int m = text1.size(), n = text2.size();
if (m == 0 || n == 0) {
return 0;
}

// f[i][j] 表示 text1[...i] 和 text2[...j] 最长公共子序列的长度
vector<vector<int>> f(m+1, vector<int>(n+1));
// 状态初始化
for (int i = 0; i <= m; i++) {
f[i][0] = 0;
}
for (int i = 0; i <= n; i++) {
f[0][i] = 0;
}

// 状态计算
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (text1[i-1] == text2[j-1]) {
f[i][j] = f[i-1][j-1] + 1;
} else {
f[i][j] = max(f[i-1][j], f[i][j-1]);
}
}
}

// 从右下角开始回溯 DP 表,构造实际的 LCS 字符串。
// 如果 text1[i-1] == text2[j-1],说明这个字符属于 LCS。
// 否则,根据 dp[i-1][j] 和 dp[i][j-1] 的大小决定方向。
string lcs;
int i = m, j = n;
while (i > 0 && j > 0) {
if (text1[i-1] == text2[j-1]) {
lcs.push_back(text1[i-1]);
i--, j--;
} else if (f[i-1][j] > f[i][j-1]) {
i--;
} else {
j--;
}
}
reverse(lcs.begin(), lcs.end()); // 反转得到正确顺序
// cout << lcs << endl;

return f[m][n];
}
};

int main() {
Solution solution;
vector<string> text1_cases = {
"abcde", "abc", "abc"
};
vector<string> text2_cases = {
"ace", "abc", "def"
};

for (int i = 0; i < text1_cases.size(); i++) {
string text1 = text1_cases[i];
string text2 = text2_cases[i];
int result = solution.longestCommonSubsequence(text1, text2);

cout << "Input: text1 = \"" << text1
<< "\", text2 = \"" << text2 << "\"" << endl;
cout << "Output: " << result << endl;
}

return 0;
}

leetcode1143:最长公共子序列
https://lcf163.github.io/2024/05/26/leetcode1143:最长公共子序列/
作者
乘风的小站
发布于
2024年5月26日
许可协议