动态规划可以求出最长公共子序列的长度,dp[i][j]表示以i-1结尾的s1和以j-1结尾的s2之间的最长公共子序列长度,由dp[i-1][j]、dp[i][j-1]以及dp[i-1][j-1]这三个上一状态推导出当前状态。

难点在于如何根据dp表的信息得到具体的子序列。从dp的右下角到左上角方向遍历dp数组,途中首次遇到的s1[i-1]==s2[j-1]时的字符s1[i-1]就是公共子串中的字符。

class Solution {
public:
    /**
     * longest common subsequence
     * @param s1 string字符串 the string
     * @param s2 string字符串 the string
     * @return string字符串
     */
    string LCS(string s1, string s2) {
        int m=s1.size();
        int n=s2.size();
        vector<vector<int>> dp(m+1,vector<int>(n+1,0));
        for(int i=1;i<=m;i++){
            for(int j=1;j<=n;j++){
                if(s1[i-1]==s2[j-1]) dp[i][j]=dp[i-1][j-1]+1;
                else dp[i][j]=max(dp[i-1][j-1],max(dp[i-1][j],dp[i][j-1]));
            }
        }
        string result{};
        for(int i=m,j=n;dp[i][j]>=1;){
            if(s1[i-1]==s2[j-1]){
                result+=s1[i-1];
                i--;
                j--;
            }
            else if(dp[i-1][j]>=dp[i][j-1]) i--;
            else j--;
        }
        reverse(result.begin(),result.end());
        return result.empty()? "-1" : result;
    }
};