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