题目
给定两个长度分别为N和M的字符串A和B,求既是A的子序列又是B的子序列的字符串长度最长是多少。
输入格式
第一行包含两个整数N和M。
第二行包含一个长度为N的字符串,表示字符串A。
第三行包含一个长度为M的字符串,表示字符串B。字符串均由小写字母构成。
输出格式
输出一个整数,表示最大长度。
数据范围
1≤N≤ 1000
- 输入样例:
4 5
acbd
abedc
- 输出样例
3
题解
import java.util.Scanner;
/**
* @author akuya
* @create 2023-07-25-19:09
*/
public class LongestCom {
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) {
Scanner scanner=new Scanner(System.in);
n=scanner.nextInt();
m=scanner.nextInt();
//java 不能直接给字符数组赋值,所以用字符串转型一下
String a1=scanner.next();
String b1=scanner.next();
char ta[]=a1.toCharArray();
char tb[]=b1.toCharArray();
System.arraycopy(ta, 0, a, 1, n);
System.arraycopy(tb, 0, b, 1, m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
f[i][j]=Math.max(f[i-1][j],f[i][j-1]);
if(a[i]==b[j])f[i][j]=Math.max(f[i][j],f[i-1][j-1]+1);
}
System.out.println(f[n][m]);
}
}
思路
本题思路如下图所示
f[i][j]表示在a中前i个字母与在b中前j个字母中的最长子序列,那么就可以分为包含ai包含bi,不包含ai和bi,只包含ai或者只包含bi四种状态情况,f[i-1][j]又与f[i][j-1]一桶包含了f[i-1][j-1]。所以实际代码只有三种情况。
其实仔细分析,f[i-1][j]中不仅仅是只包含bi的情况,它包含了其他情况,但是求最大值,有重复数据不影响最终结果,也就无所谓了。