题目:
给定两个长度分别为 N 和 M 的字符串 A 和 B,求既是 A 的子序列又是 B 的子序列的字符串长度最长是多少。
输入格式
第一行包含两个整数 N 和 M。
第二行包含一个长度为 N 的字符串,表示字符串 A。
第三行包含一个长度为 M 的字符串,表示字符串 B。
字符串均由小写字母构成。
输出格式
输出一个整数,表示最大长度。
数据范围
1≤N,M≤1000
输入样例:
4 5 acbd abedc
输出样例:
3
DP分析:
状态表示:使用
- 集合 : 表示A的 和B的 的所有公共子序列的方案
- 属性:取所有公共子序列长度最大值
状态计算:
要保证不重不漏。
- 如果 ,即 :
- 如果 ,那么就从, 中选最大:
有一个问题就是, 表示的是从 A的 和 B 的 中选,但是其实 在其中不是一定会被选上的,是可选可不选的。但是我们要求的是不要 ,而必选 的那一部分集合方案。因此 与我们的需要的条件不完全相等。
但仍然可以是用 来表示 条件,这是因为条件是包含在 中的,即条件的情况是 的子集,而求的是max,所以对结果不影响。主要是不含 的那一部分可以用 来表示, 包含了 ,所以我们都不用考虑 这部分,因为已经包含在 和 中了。
即 是 和 的并集。
代码:
import java.io.*;
import java.util.*;class Main{static int N = 1010;static int n,m;static char[] a = new char[N];static char[] b = new char[N];static int[][] f = new int[N][N]; public static void main(String[] args) throws IOException{BufferedReader in = new BufferedReader(new InputStreamReader(System.in));String[] s = in.readLine().split(" ");n = Integer.parseInt(s[0]);m = Integer.parseInt(s[1]);String s1 = in.readLine();String s2 = in.readLine();for(int i=1;i<=n;i++)a[i] = s1.charAt(i-1);for(int i=1;i<=m;i++)b[i] = s2.charAt(i-1);// DPfor(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(a[i]==b[j]) f[i][j] = f[i-1][j-1]+1;else{f[i][j] = Math.max(f[i-1][j],f[i][j-1]);}}}System.out.println(f[n][m]);}
}