牛客题解 | 最长公共子序列

题目

题目链接

解题思路

这是一个最长公共子序列(LCS)问题。关键点:

  1. 动态规划定义

    • \(dp[i][j]\) 表示 \(A\) 的前 \(i\) 个字符和 \(B\) 的前 \(j\) 个字符的最长公共子序列长度
    • \(0 \leq i \leq n, 0 \leq j \leq m\)
  2. 状态转移

    • \(A[i-1] == B[j-1]\) 时:\(dp[i][j] = dp[i-1][j-1] + 1\)
    • 否则:\(dp[i][j] = \max(dp[i-1][j], dp[i][j-1])\)
  3. 边界条件

    • \(dp[0][j] = 0\)
    • \(dp[i][0] = 0\)

代码

class LCS {
public:
    int findLCS(string A, int n, string B, int m) {
        vector<vector<int>> dp(n + 1, vector<int>(m + 1, 0));
        
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= m; j++) {
                if(A[i-1] == B[j-1]) {
                    dp[i][j] = dp[i-1][j-1] + 1;
                } else {
                    dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
                }
            }
        }
        
        return dp[n][m];
    }
};
import java.util.*;

public class LCS {
    public int findLCS(String A, int n, String B, int m) {
        // write code here
        int[][] dp = new int[n + 1][m + 1];
        
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= m; j++) {
                if(A.charAt(i-1) == B.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[n][m];
    }
}
# -*- coding:utf-8 -*-

class LCS:
    def findLCS(self, A, n, B, m):
        dp = [[0] * (m + 1) for _ in xrange(n + 1)]
        
        for i in xrange(1, n + 1):
            for j in xrange(1, m + 1):
                if A[i-1] == B[j-1]:
                    dp[i][j] = dp[i-1][j-1] + 1
                else:
                    dp[i][j] = max(dp[i-1][j], dp[i][j-1])
        
        return dp[n][m]

算法及复杂度

  • 算法:动态规划
  • 时间复杂度:\(\mathcal{O(nm)}\),需要填充整个 \(dp\)
  • 空间复杂度:\(\mathcal{O(nm)}\),需要二维 \(dp\) 数组
posted @ 2025-03-07 11:31  wangxiaoxiao  阅读(25)  评论(0)    收藏  举报