1. 程式人生 > >[LeeCode] Distinct Subsequences解法

[LeeCode] Distinct Subsequences解法

題目

Given a string S and a string T, count the number of distinct subsequences of S which equals T.A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, "ACE"

 is a subsequence of "ABCDE" while "AEC" is not).

具體例子見原題。

分析

肯定又是動態規劃 。標準套路是構建dp陣列,初始化第一行和第一列,找出遞推公式。但是不同的題目對應著不同的遞推公式,第一次見到一種題型很難直接找到遞推公式,所以只能積累,或者:自己先手動完成一個dp陣列然後找規律。

該題目的例子是Input: S = "rabbbit", T = "rabbit" Output: 3,在此基礎上構建的dp陣列如下:

  Ø r a b b b i t
Ø 1 1 1 1 1 1 1 1
r 0 1 1 1 1 1 1 1
a 0 0 1 1 1 1 1 1
b 0 0 0 1 2 3 3 3
b 0 0 0 0 1 3 3 3
i 0 0 0 0 0 0 3 3
t 0 0 0 0 0 0 0 3

如果t的長度大於s的長度,那必然是0.然後如果t的長度為0的話,那必然是1.因為空串也算作一個子串。

我們通過觀察上面的二維陣列可以發現,當更新到dp[i][j]時,dp[i][j] >= dp[i][j - 1] 總是成立,再進一步觀察發現,當 t[i - 1] == s[j - 1] 時,dp[i][j] = dp[i][j - 1] + dp[i - 1][j - 1],若不等, dp[i][j] = dp[i][j - 1],所以,綜合以上,遞推式為:

dp[i][j] = dp[i][j - 1] + (s[i - 1] == t[j - 1] ? dp[i - 1][j - 1] : 0)

我花了一段時間區試圖理解這個規律背後的含義,但是想了半天感覺還是有點亂。動態規劃最根本的部分無非就是遞推公式,但是這個遞推不是隨隨便便就能推出來的,所以最好的解決方式還是多做題多積累。

程式碼

class Solution {
public:
    int numDistinct(string s, string t) {
        int row = t.size();
        int col = s.size();
        int dp[row+1][col+1] = {0};
        for(int i=0;i<=col;i++) dp[0][i] = 1;
        for(int i=1;i<=row;i++) dp[i][0] = 0;
        for(int i=1;i<=row;i++)
            for(int j=1;j<=col;j++)
            {
                dp[i][j] = dp[i][j - 1] + (t[i - 1] == s[j - 1] ? dp[i - 1][j - 1] : 0);
            }
        return dp[row][col];
    }
};