【常见面试算法】最长公共子序列

给定两个长度分别为N和M的字符串A和B,求既是A的子序列又是B的子序列的字符串长度最长是多少。

输入格式

第一行包含两个整数N和M。

第二行包含一个长度为N的字符串,表示字符串A。

第三行包含一个长度为M的字符串,表示字符串B。

字符串均由小写字母构成。

输出格式

输出一个整数,表示最大长度。

数据范围

1≤N≤10001≤N≤1000,

输入样例:

4 5
acbd
abedc

输出样例:

3
解答:
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int m = in.nextInt();
        in.nextLine();
        char[] s1 = in.nextLine().toCharArray();
        char[] s2 = in.nextLine().toCharArray();
        //dp[i][j]的含义是:s1[0-i]和s2[0-j]的最长公共子序列
        int[][] dp = new int[n][m];
        //初始化,两个字符串的第一个字符是否相等
        dp[0][0] = s1[0] == s2[0] ? 1 : 0;
        //初始化,把第一行和第一列进行初始化,由于判断的是子序列,所以
        //只要有一个字符相等,后面的dp就都是1
        for (int i = 1; i < n; i++) {
            dp[i][0] = Math.max(dp[i - 1][0], s1[i] == s2[0] ? 1 : 0);
        }
        for (int i = 1; i < m; i++) {
            dp[0][i] = Math.max(dp[0][i - 1], s1[0] == s2[i] ? 1 : 0);
        }
        
        for (int i = 1; i < n; i++) {
            for (int j = 1; j < m; j++) {
                //默认情况,dp[i][j]应该是将s1或者s2去掉一个字符后的dp的较大值
                dp[i][j] = Math.max(dp[i][j - 1],dp[i - 1][j]);
                //若s1[i]==s2[j],还需要判断和dp[i - 1][j - 1] + 1比较后的较大值
                if (s1[i] == s2[j]) {
                    dp[i][j] = Math.max(dp[i][j],dp[i - 1][j - 1] + 1);
                }
            }
        }
        System.out.println(dp[n - 1][m - 1]);
    }
}




全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务