Acwing.897 最长公共子序列(动态规划)

题目

给定两个长度分别为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]);
    }
}

思路

本题思路如下图所示
Acwing.897 最长公共子序列(动态规划)_第1张图片
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的情况,它包含了其他情况,但是求最大值,有重复数据不影响最终结果,也就无所谓了。

你可能感兴趣的:(java算法实录,动态规划,算法)