LeetCode #1143:Longest Common Subsequence(最长公共子序列)

题目描述

本题是一类经典的二维动态规划问题。设 dp[i][j] 为 text1[0…i] 与 text2[0…j] 的最长公共子序列,那么本问题的状态转移方程为:

if(text1[i] == text2[j]) {
    dp[i][j] = 1 + dp[i-1][j-1]; //末尾字符相等时
} else {
    dp[i][j] = max(dp[i-1][j], dp[i][j-1]); //末尾字符不相等时
}

推算出状态转移方程后,写出代码求解就十分容易了。

方法一:递归(超时)

class Solution {
public:
    int longestCommonSubsequence(string text1, string text2) {
        return ans(text1, text2, text1.length() - 1, text2.length() - 1);
    }

    int ans(string &text1, string &text2, int i, int j) { //i、j分别表示对text1、text2从下标0到i、j闭区间范围的字串进行求解
        if(i < 0 || j < 0)
            return 0;
        else {
            if(text1[i] == text2[j])
                return ans(text1, text2, i - 1, j - 1) + 1;
            else
                return max(ans(text1, text2, i - 1, j), ans(text1, text2, i, j - 1));
        }

    }
};

方法二:记忆化搜索

class Solution {
public:
    int longestCommonSubsequence(string text1, string text2) {

        vector< vector<int> > flag(text1.length(), vector<int>(text2.length(), -1)); //将递归的结果储存到该数组中

        return ans(text1, text2, text1.length() - 1, text2.length() - 1, flag);
    }

    int ans(string &text1, string &text2, int i, int j, vector< vector<int> > &flag) {
        if(i < 0 || j < 0)
            return 0;
        else {
            if(flag[i][j] != -1) //若该结果已经先前被计算过,直接返回flag数组中对应索引的内容
                return flag[i][j];
            if(text1[i] == text2[j])
                flag[i][j] = ans(text1, text2, i - 1, j - 1, flag) + 1;
            else
                flag[i][j] = max(ans(text1, text2, i - 1, j, flag), ans(text1, text2, i, j - 1, flag));
            return flag[i][j];
        }

    }

};

方法三:动态规划

class Solution {
public:
    int longestCommonSubsequence(string text1, string text2) {
        
        if(text1.length() == 0 || text2.length() == 0)
            return 0;

        int n = text1.length();
        int m = text2.length();
        vector< vector<int> > dp(n, vector<int>(m, -1));

        dp[0][0] = (text1[0] == text2[0] ? 1 : 0); //初始化dp[0][0]

        for(int i = 1; i < n; i ++) { //初始化dp[1...n-1][0]
            dp[i][0] = (text1[i] == text2[0] ? 1 : dp[i - 1][0]);
            
        }
        for(int j = 1; j < m; j ++) { //初始化dp[0][1...m-1]
            dp[0][j] = (text1[0] == text2[j] ? 1 : dp[0][j - 1]);
        }
        
        for(int i = 1; i < n; i ++) {
            for(int j = 1; j < m; j ++) {
                if(text1[i] == text2[j])
                    dp[i][j] = 1 + dp[i - 1][j - 1];
                else
                    dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
            }
        }

        return dp[n - 1][m - 1];
    }

};

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注