📜  算法测验|须藤放置[1.8] |问题11(1)

📅  最后修改于: 2023-12-03 15:41:10.011000             🧑  作者: Mango

算法测验 - 须藤放置[1.8] - 问题11

这是一道关于最长公共子序列(Longest Common Subsequence)问题的算法题。最长公共子序列是指两个字符串中都出现的最长的子序列,这里的子序列指的是字符串中不一定连续但相对位置不变的一组字符。例如,"ABCD" 和 "ACDF" 的最长公共子序列是 "ACD","ABCDEF" 和 "FBDAMN" 的最长公共子序列是 "BD"。

题目描述

给定两个字符串 s1 和 s2,请找出它们的最长公共子序列,并返回其长度。

示例

输入:

s1 = "abcde", s2 = "ace"

输出:

3

解释: 最长公共子序列是 "ace",长度为 3。

解题思路

最长公共子序列问题可以通过动态规划来解决。我们可以用一个二维数组 dp[i][j] 来保存 s1[0...i-1] 和 s2[0...j-1] 的最长公共子序列的长度。如果 s1[i-1] 和 s2[j-1] 相等,那么 dp[i][j] 等于 dp[i-1][j-1] + 1,因为两个字符串的最长公共子序列中必然包含它们的最后一个字符。如果 s1[i-1] 和 s2[j-1] 不相等,那么 dp[i][j] 等于 dp[i-1][j] 和 dp[i][j-1] 中的最大值,因为两个字符串的最长公共子序列中必然不包含它们的最后一个字符。最后,dp[s1.length()][s2.length()] 就是两个字符串的最长公共子序列的长度。

代码实现
public int longestCommonSubsequence(String s1, String s2) {
    int m = s1.length(), n = s2.length();
    int[][] dp = new int[m+1][n+1];
    for (int i = 1; i <= m; i++) {
        for (int j = 1; j <= n; j++) {
            if (s1.charAt(i-1) == s2.charAt(j-1)) {
                dp[i][j] = dp[i-1][j-1] + 1;
            } else {
                dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]);
            }
        }
    }
    return dp[m][n];
}
总结

最长公共子序列是经典的问题,其解法也是动态规划的经典题目之一。学习和掌握动态规划的思想和技巧,对于算法工程师来说是非常重要的。