[LeetCode] 115. 不同的子序列(動態規劃)

115. 不同的子序列(動態規劃)

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

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

題目數據保證答案符合 32 位帶符號整數範圍。

在這裏插入圖片描述

解題思路: 觀察此題屬於求子序列的問題,聯想到用DP解題,然後定義dp[i][j]表示字符串s前j個字符中包含字符串t前i個字符的個數,但是到這兒就斷片兒了,參考了一下grandyang大神的思路,發現通過列舉找出了狀態轉移方程,按照這個思路解完題後,想了想,如果不通過列舉,可不可以這麼找到狀態轉移方程,一般來說,想找出狀態轉移方程我們需要先列出上一個狀態有哪些,然後當前狀態與上一個狀態的關聯是什麼,另外一點是,在分解上一個狀態時,要找一個標準,使得分解的狀態互斥、完備,OK,我們相信上一個狀態是不是可以分解爲[i-1,j],[i,j-1],[i-1][j-1],(t->s),但是對於狀態[i,j-1]是不需要且不成立的,因爲s先增長,t後增長才有意義,那剩下的就是狀態[i-1,j]和狀態[i-1][j-1],對於狀態[i-1][j-1]要求s[j]==st[i]才能對狀態[i][j]有貢獻,OK,至此,即可分析出狀態轉移方程~

// dp[i][j] = dp[i][j - 1] + (T[i - 1] == S[j - 1] ? dp[i - 1][j - 1] : 0)
class Solution {
public:
    int numDistinct(string s, string t) {
        int m = t.size(), n = s.size();
        vector<vector<long>> dp(m + 1, vector<long>(n + 1, 0));
        for (int j = 0; j <= n; ++j)  dp[0][j] = 1;
        for (int i = 1; i <= m; ++i) {
            for (int j = 1; j <= n; ++j) {
                dp[i][j] = dp[i][j - 1] + (t[i - 1] == s[j - 1] ? dp[i - 1][j - 1] : 0);
            }
        }
        return dp[m][n];
    }
};

————————————

參考資料:

https://www.cnblogs.com/grandyang/p/4294105.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章