[LintCode] Distinct Subsequences
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"
is a subsequence of "ABCDE"
while "AEC"
is not).
Given S = "rabbbit"
, T = "rabbit"
, return 3
.
Do it in O(n2) time and O(n) memory.
O(n2) memory is also acceptable if you do not know how to optimize memory.
SOLUTION:
以下大部分摘自 http://www.cnblogs.com/yuzhangcmu/p/4196373.html
遇到这种两个串的问题,很容易想到DP。但是这道题的递推关系不明显。可以先尝试做一个二维的表int[][] dp,用来记录匹配子序列的个数(以S ="rabbbit"
,T = "rabbit"
为例):
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
看这个图更直接,我们看如果S(i) == T(j) 时,先看S(i - 1)跟T(j - 1) 去匹配,然后还有一种情况就是用S(i - 1)跟T(j) 去匹配 ==> result[i][j] = result[i - 1][j - 1] + result[i - 1][j]==>意思就是既然这个位置两个位置相等了,那么T(j)可以匹配也可以不匹配,有两个情况,都要考虑。
如果S(i) != T(j) 那么就必须看S(i - 1) T(j - 1)之间能不能匹配了 ==> result[i][j] = result[i - 1][j - 1]
再看初始化,第一行第一列明显需要初始化,第一行意思是,S不空,T是空的,所以肯定存在1个(空集),第一列就是说,S空,不管T是什么,肯定是0个LCS。
看代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class Solution { /** * @param S, T: Two string. * @return: Count the number of distinct subsequences */ public int numDistinct(String S, String T) { if (S == null || T == null){ return 0; } int[][] result = new int[S.length() + 1][T.length() + 1]; for (int i = 0; i <= S.length(); i++){ result[i][0] = 1; } for (int i = 1; i <= S.length(); i++){ for (int j = 1; j <= T.length(); j++){ if (S.charAt(i - 1) == T.charAt(j - 1)){ result[i][j] = result[i - 1][j] + result[i - 1][j - 1];//needs T[j] or not } else { result[i][j] = result[i - 1][j]; } } } return result[S.length()][T.length()]; } }