最长公共子序列问题(LCS)

可以用动态规划来解决LCS问题,假设有字符串X和字符串Y,dp[i,j]表示的是X的前i个字符和Y的前j个字符的最长公共子序列的的长度。如果X[i]==Y[j],那么这个字符就可以和之前的LCS一起构成一个新的LCS; 如果X[i]!=Y[j],那么分别考虑dp[i-1,j]和dp[i,j-1],选择其中较大的为LCS。

if(i==0||j==0)
    dp[i,j]=0;
else if(X[i]==Y[j])
    dp[i,j]=dp[i-1,j-1]+1;
else
    dp[i,j]=max(dp[i-1,j],dp[i,j-1]);

最长递增子序列(LIS)

要求长度为i的序列的Ai{a1,a2,……,ai}最长递增子序列,需要先求出序列Ai-1{a1,a2,……,ai-1}中以各元素(a1,a2,……,ai-1)作为最大元素的最长递增序列,然后把所有这些递增序列与ai比较,如果某个长度为m序列 的末尾元素aj(j<i)比ai要小,则将元素ai加入这个递增子序列,得到一个新的长度为m+1的新序列,否则其长度不变,将处理后的所有i个序列的长度进行比较,其中最长的序列就是所求的最长递增子序列。

int lengthOfLIS(vector<int>& nums) {
    // 时间复杂度为O(N^2)
    int n = nums.size();
    if (n < 2) {
        return n;
    }
    // dp[i]代表以nums[i]结尾的最长递增子序列长度
    vector<int> dp(n, 1);
    // 对nums[i]遍历[0, i)区间,当nums[i] > nums[j]的时候,说明nums[i]可以放在nums[j]之后,
    // 此时最长递增子序列长度为dp[j] + 1
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < i; j++) {
            if (nums[i] > nums[j]) {
                dp[i] = max(dp[j] + 1, dp[i]);
            }
        }
    }
    int res = 0;
    for(int i = 0; i < dp.size(); i++) {
        res = max(res, dp[i]);
    }
    return res;
}