1. 程式人生 > >【LeetCode】115. 不同的子序列 結題報告 (C++)

【LeetCode】115. 不同的子序列 結題報告 (C++)

原題地址:https://leetcode-cn.com/problems/distinct-subsequences/description/

題目描述:

給定一個字串 S 和一個字串 T,計算在 S 的子序列中 T 出現的個數。

一個字串的一個子序列是指,通過刪除一些(也可以不刪除)字元且不干擾剩餘字元相對位置所組成的新字串。(例如,"ACE" 是 "ABCDE" 的一個子序列,而 "AEC" 不是)

示例 1:

輸入: S = "rabbbit", T = "rabbit"
輸出: 3
解釋:

如下圖所示, 有 3 種可以從 S 中得到 "rabbit" 的方案。
(上箭頭符號 ^ 表示選取的字母)

rabbbit
^^^^ ^^
rabbbit
^^ ^^^^
rabbbit
^^^ ^^^
示例 2:

輸入: S = "babgbag", T = "bag"
輸出: 5
解釋:

如下圖所示, 有 5 種可以從 S 中得到 "bag" 的方案。 
(上箭頭符號 ^ 表示選取的字母)

babgbag
^^ ^
babgbag
^^    ^
babgbag
^    ^^
babgbag
  ^  ^^
babgbag
    ^^^
 

解題方案:

動態規劃的題目,首先找到遞推公式:

dp[i][j]表示字串T的從0開始長度為i的子串和字串S的從0開始長度為j的子串的匹配總個數。(s的長度時大於等於t的,否則輸出為0) 
設定一個dp[t.length+1][s.length+1]  
初始化情況: 
首先dp[0][0]=1;表示空的字串t和空的字串s是匹配的。 
然後dp[0][1….s.length]=1;表示的是空的字串t,與不為空的字串s是相互匹配的,而且匹配的個數為1。 
dp[1…..t.length][0]=0; 表示不為空的字串t, 空的字串s,他們匹配的總個數為0;

當t[i-1]==s[j-1]相同時: dp[i][j]=dp[i-1][j-1]+dp[i][j-1] 
當t[i-1]!=s[j-1]不相同: dp[i][j]=dp[i][j-1]。

最後輸出dp[t.length][s.length]。

class Solution {
public:
    int numDistinct(string s, string t) {
        int l1 = t.size();
        int l2 = s.size();
        int dp[l1 + 1][l2 + 1];
        
        for(int i = 0; i< l2 + 1; i++)  //首先i對於的就是字串t裡面的索引
            dp[0][i] = 1;

        for(int i = 1; i < l1 + 1; i++)  //首先從第二行開始計算,第一行中第一個數總是為1的。因為兩個空字串是匹配的。
            dp[i][0] = 0;

        for(int i = 1; i <= l1; i++)     //動態規劃
            for(int j = 1; j <= l2; j++)    //首先j對於的就是字串s裡面的索引。(s>t)
                if(t[i - 1] != s[j - 1])
                    dp[i][j] = dp[i][j - 1];
                else
                    dp[i][j] = dp[i - 1][j - 1] + dp[i][j - 1];

        return dp[l1][l2];
    }
};