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).
Here is an example:
S = "rabbbit"
, T = "rabbit"
Return 3
.
解题:首先我们必须把这个题理解清楚。这个题的描述是有点模糊,而且例子举的不是很好,所以会产生误解。正确的理解方式为:
在S中找和T相同的不同子序列的数目。下面以这个例子为例来解释:
S中包含的字符如下:{'r','a','b','b','b','i','t'}
中间三个b可以有三种删除方法,删除前两个,删除后两个,删除两头,这样就可以得到通过三种不同删除方法得到的子序列。这几个字序列满足和T相同的条件。
本题只要理解清楚题意,用动态规划来做还是很容易理清楚思路的。
矩阵results[i][j] 用来存储S[0...i - 1]得到和T[0...j - 1]相同的不同子序列的数目。递归如下:
如果S[i-1] == T[j - 1], 那么分两种情况来考虑(1)都不包含这两个相同的字符情况下产生的不同字序列数目,即results[i - 1][j - 1]; (2)因为是计算从S中删除字符得到子序列和T相同的不同子序列的数目,因此,我们还需加上在T加上T[j -1]个字符时和S[1...i - 2]计算得到不同序列的数目,即results[i - 1][j];可以证明,这两种情况能保证比较的完备性。
如果S[i - 1] != T[j - 1],那么S[ i - 1]这个字符加入比较的序列并不能产生任何效果,因此results[i][j] = results[i - 1][j];
初始化的情况很容易理解,这里就不再赘述。
class Solution {
public:
int numDistinct(string S, string T) {
int ssize = S.size();
int tsize = T.size();
int results[ssize + 1][tsize + 1];
for(int i = 0; i <= ssize; i++){
results[i][0] = 1;
}
for(int j = 1; j <= tsize; j++){
results[0][j] = 0;
}
for(int i = 1; i <= ssize; i++){
for(int j = 1; j <= tsize; j++){
if(S.c_str()[i - 1] == T.c_str()[j - 1]){
results[i][j] = results[i - 1][j - 1] + results[i - 1][j];
}
else{
results[i][j] = results[i - 1][j];
}
}
}
return results[ssize][tsize];
}
};