AcWing 897. 最长公共子序列
给定两个长度分别为 NN 和 MM 的字符串 AA 和 BB,求既是 AA 的子序列又是 BB 的子序列的字符串长度最长是多少。
输入格式
第一行包含两个整数 NN 和 MM。
第二行包含一个长度为 NN 的字符串,表示字符串 AA。
第三行包含一个长度为 MM 的字符串,表示字符串 BB。
字符串均由小写字母构成。
输出格式
输出一个整数,表示最大长度。
数据范围
1≤N,M≤10001≤N,M≤1000
输入样例:
4 5
acbd
abedc
输出样例:
3
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt(), m = sc.nextInt();
String s1 = sc.next(), s2 = sc.next();
int[][] f = new int[n + 1][m + 1];
for (int i = 1; i <= n; i++) {
char c1 = s1.charAt(i - 1);
for (int j = 1; j <= m; j++) {
char c2 = s2.charAt(j - 1);
f[i][j] = Math.max(f[i][j-1], f[i-1][j]);
if (c1 == c2)
f[i][j] = Math.max(f[i][j], f[i-1][j-1] + 1);
}
}
System.out.println(f[n][m]);
}
}
1092. 最短公共超序列
给出两个字符串 str1 和 str2,返回同时以 str1 和 str2 作为子序列的最短字符串。如果答案不止一个,则可以返回满足条件的任意一个答案。
(如果从字符串 T 中删除一些字符(也可能不删除,并且选出的这些字符可以位于 T 中的 任意位置),可以得到字符串 S,那么 S 就是 T 的子序列)
示例:
输入:str1 = “abac”, str2 = “cab” 输出:“cabac” 解释: str1 = “abac” 是 “cabac” 的一个子串,因为我们可以删去 “cabac” 的第一个 “c”得到 “abac”。 str2 = “cab” 是 “cabac” 的一个子串,因为我们可以删去 “cabac” 末尾的 “ac” 得到 “cab”。 最终我们给出的答案是满足上述属性的最短字符串。
提示:
- 1 <= str1.length, str2.length <= 1000
- str1 和 str2 都由小写英文字母组成。
思路:
涉及了LCS求具体方案
class Solution {
public String shortestCommonSupersequence(String s1, String s2) {
int n = s1.length(), m = s2.length();
int[][] f = new int[n + 1][m + 1];
for (int i = 1; i <= n; i++) {
char c1 = s1.charAt(i - 1);
for (int j = 1; j <= m; j++) {
char c2 = s2.charAt(j - 1);
if (c1 == c2)
f[i][j] = f[i - 1][j - 1] + 1;
f[i][j] = Math.max(f[i][j], Math.max(f[i - 1][j], f[i][j - 1]));
}
}
int x = n, y = m;
StringBuilder sb = new StringBuilder();
while (x > 0 || y > 0) {
if (x == 0) {
sb.append(s2.charAt(y - 1));
y--;
} else if (y == 0) {
sb.append(s1.charAt(x - 1));
x--;
} else {
if (s1.charAt(x - 1) == s2.charAt(y - 1)) {
sb.append(s1.charAt(x - 1));
x--;
y--;
} else {
if (f[x][y - 1] == f[x][y]) {
sb.append(s2.charAt(y - 1));
y--;
} else {
sb.append(s1.charAt(x - 1));
x--;
}
}
}
}
return sb.reverse().toString();
}
}