首页 > 代码库 > 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).
Here is an example:
S = "rabbbit", T = "rabbit"
Return 3.
思路:遍历T,依次确定满足T[0],T[1],...T[m]的元素S[i]的位置(即i)和路径数。满足T[j]的元素必然出现在某个满足T[j-1]的元素之后,且其路径数为该满足T[j-1]的元素及其之前出现的所有满足T[j-1]的元素的路径数之和。最后,将满足T[m]的所有元素的路径数加和即为所求。
1 class Solution { 2 public: 3 int numDistinct( string S, string T ) { 4 int slen = S.length(), tlen = T.length(); 5 if( tlen == 0 ) { return 1; } 6 if( slen < tlen ) { return 0; } 7 vector<pair<int,int>> idxCnt( 2, make_pair( -1, 1 ) ); 8 idxCnt.back().first = slen-tlen; 9 for( int index = 0; index < tlen; ++index ) {10 vector<pair<int,int>> newIdxCnt;11 for( size_t i = 1; i != idxCnt.size(); ++i ) {12 for( int k = idxCnt[i-1].first+1; k <= idxCnt[i].first; ++k ) {13 if( S[k] != T[index] ) { continue; }14 newIdxCnt.push_back( make_pair( k, idxCnt[i-1].second ) );15 }16 idxCnt[i].second += idxCnt[i-1].second;17 }18 if( newIdxCnt.empty() ) { return 0; }19 newIdxCnt.push_back( idxCnt.back() );20 idxCnt = newIdxCnt;21 ++idxCnt.back().first;22 }23 int numDist = 0;24 for( size_t i = 1; i != idxCnt.size(); ++i ) {25 numDist += idxCnt[i-1].second;26 }27 return numDist;28 }29 };
上述算法的思路还是比较清晰的。不过,要描述清楚却实在是费劲,实现起来也比较麻烦。我们来看网上基于DP的算法:
numDist[i][j]表示S(0:i)经过删除字符变到T(0:j)的方法数。若S[i]==T[j],有numDist[i][j] = numDist[i-1][j-1] + numDist[i-1][j];若S[i]!=T[j],则numDist[i][j] = numDist[i-1][j]。
1 class Solution { 2 public: 3 int numDistinct( string S, string T ) { 4 int sLen = S.length(), tLen = T.length(); 5 if( sLen < tLen ) { return 0; } 6 vector<vector<int>> numDist( sLen+1, vector<int>( tLen+1, 0 ) ); 7 for( int i = 1; i <= sLen; ++i ) { 8 numDist[i-1][0] = 1; 9 for( int j = 1; j <= tLen; ++j ) {10 if( S[i-1] != T[j-1] ) {11 numDist[i][j] = numDist[i-1][j];12 } else {13 numDist[i][j] = numDist[i-1][j-1] + numDist[i-1][j];14 }15 }16 }17 return numDist[sLen][tLen];18 }19 };