[LeetCode] Distinct Subsequences 不同的子序列
Given a string S and a string T, count the number of distinct subsequences of T in S.
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).
Here is an example:
S = "rabbbit"
, T = "rabbit"
Return 3
.
看到有關字串的子序列或者配準類的問題,首先應該考慮的就是用動態規劃Dynamic Programming來求解,這個應成為條件反射。而所有DP問題的核心就是找出遞推公式,想這道題就是遞推一個二維的dp陣列,下面我們從題目中給的例子來分析,這個二維dp陣列應為:
Ø r a b b b i t Ø 1 1 1 1 1 1 1 1 r 0 1 1 1 1 1 1 1a 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 dp[T.size() + 1][S.size() + 1]; for (int i = 0; i <= S.size(); ++i) dp[0][i] = 1; for (int i = 1; i <= T.size(); ++i) dp[i][0] = 0; for (int i = 1; i <= T.size(); ++i) { for (int j = 1; j <= S.size(); ++j) { dp[i][j] = dp[i][j - 1] + (T[i - 1] == S[j - 1] ? dp[i - 1][j - 1] : 0); } } return dp[T.size()][S.size()]; } };