897. 最长公共子序列
题目链接: 897. 最长公共子序列
题目描述
给定两个长度分别为 N 和 M 的字符串 A 和 B,求既是 A 的子序列又是 B 的子序列的字符串长度最长是多少。
输入格式
第一行包含两个整数 N 和 M。
第二行包含一个长度为 N 的字符串,表示字符串 A。
第三行包含一个长度为 M 的字符串,表示字符串 B。
字符串均由小写字母构成。
输出格式
输出一个整数,表示最大长度。
数据范围
1 ≤ N,M ≤ 1000
输入样例
4 5
acbd
abedc
输出样例:
3
题目解法:
(1)暴力搜索(会超时)
import java.util.*;
public class Main{
static int n = 0;
static int m = 0;
static String a = null;
static String b = null;
public static int dfs(int i,int j){
if (i < 0 || j < 0){
return 0;
}
if (a.charAt(i) == b.charAt(j)){
return dfs(i - 1, j - 1) + 1;
}
return Math.max(dfs(i - 1, j), dfs(i, j - 1));
}
public static void main(String[] args){
Scanner in = new Scanner(System.in);
n = in.nextInt();
m = in.nextInt();
a = in.next();
b = in.next();
int res = dfs(n - 1,m - 1);
System.out.println(res);
}
}
(2)记忆化搜索
import java.util.*;
public class Main{
static int[][] f = new int[1001][1001];
static int n = 0;
static int m = 0;
static String a = null;
static String b = null;
//dfs函数代表计算a字符串中 0 ~ i 下标组成的子序列与b字符串中 0 ~ j 下标组成的子序列的最大公共长度
public static int dfs(int i,int j){
if (i < 0 || j < 0){
return 0;
}
if (f[i][j] != -1){
return f[i][j];
}
if (a.charAt(i) == b.charAt(j)){
return f[i][j] = dfs(i - 1, j - 1) + 1;
}
return f[i][j] = Math.max(dfs(i - 1, j), dfs(i, j - 1));
}
public static void main(String[] args){
Scanner in = new Scanner(System.in);
n = in.nextInt();
m = in.nextInt();
a = in.next();
b = in.next();
for (int i = 0; i < n; i++)
Arrays.fill(f[i], -1); // -1表示没用访问过
int res = dfs(n - 1,m - 1);
System.out.println(res);
}
}
(3)动态规划
import java.util.*;
public class Main{
static int[][] f = null;
public static void main(String[] args){
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int m = in.nextInt();
f = new int[n+1][m+1];
String a = in.next();
String b = in.next();
for(int i = 0;i < n;i++){
for(int j = 0;j < m;j++){
if(a.charAt(i) == b.charAt(j)){
f[i+1][j+1] = f[i][j] + 1;
}else{
f[i+1][j+1] = Math.max(f[i+1][j],f[i][j+1]);
}
}
}
System.out.println(f[n][m]);
}
}