C++實現LeetCode(115.不同的子序列)

[LeetCode] 115. 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).

Example 1:

Input: S =

“rabbbit”

, T =

“rabbit”
Output: 3

Explanation:

As shown below, there are 3 ways you can generate “rabbit” from S.
(The caret symbol ^ means the chosen letters)

rabbbit

^^^^ ^^

rabbbit

^^ ^^^^

rabbbit

^^^ ^^^

Example 2:

Input: S =

“babgbag”

, T =

“bag”
Output: 5

Explanation:

As shown below, there are 5 ways you can generate “bag” from S.
(The caret symbol ^ means the chosen letters)

babgbag

^^ ^

babgbag

^^    ^

babgbag

^    ^^

babgbag

  ^  ^^

babgbag

    ^^^

看到有關字符串的子序列或者配準類的問題,首先應該考慮的就是用動態規劃 Dynamic Programming 來求解,這個應成為條件反射。而所有 DP 問題的核心就是找出狀態轉移方程,想這道題就是遞推一個二維的 dp 數組,其中 dp[i][j] 表示s中范圍是 [0, i] 的子串中能組成t中范圍是 [0, j] 的子串的子序列的個數。下面我們從題目中給的例子來分析,這個二維 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

首先,若原字符串和子序列都為空時,返回1,因為空串也是空串的一個子序列。若原字符串不為空,而子序列為空,也返回1,因為空串也是任意字符串的一個子序列。而當原字符串為空,子序列不為空時,返回0,因為非空字符串不能當空字符串的子序列。理清這些,二維數組 dp 的邊緣便可以初始化瞭,下面隻要找出狀態轉移方程,就可以更新整個 dp 數組瞭。我們通過觀察上面的二維數組可以發現,當更新到 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] + (T[i – 1] == S[j – 1] ? dp[i – 1][j – 1] : 0)

根據以上分析,可以寫出代碼如下:

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

Github 同步地址:

https://github.com/grandyang/leetcode/issues/115

參考資料:

https://leetcode.com/problems/distinct-subsequences/

https://leetcode.com/problems/distinct-subsequences/discuss/37327/Easy-to-understand-DP-in-Java

https://leetcode.com/problems/distinct-subsequences/discuss/37412/Any-better-solution-that-takes-less-than-O(n2)-space-while-in-O(n2)-time

到此這篇關於C++實現LeetCode(115.不同的子序列)的文章就介紹到這瞭,更多相關C++實現不同的子序列內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: