[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"
"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];
}
};