题目:
Given a string S and a string T, count the number of distinct subsequences ofT 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
.
先用自己发明的笨办法。先扫描S,把S中每个字符出现的位置映射到一个vector<vector<int>>里,如abcde-> [0][1][2][3][4],然后逐次扫描T的字符,用当前字符去查找vector<vector<int>>的值(字符出现的位置),只要保证T里所有的字符都满足:当前字符的位置小于下一个字符的位置,即为一个subsequence,利用递归迭代层层深入。
c++版:
class Solution {
public:
int numDistinct(string S, string T) {
if(!S.length() or !T.length())
return 0;
vector<vector<int>> pos;
for(int t = 0; t < 256; t++) {
vector<int> temp(1);
pos.push_back(temp);
}
for(int i = 0; i < S.length(); i++) {
if(!pos[S[i]][0])
pos[S[i]][0] = i + 1;
else
pos[S[i]].push_back(i+1);
}
int count = 0;
if(!pos[T[0]][0])
return 0;
for(int j = 0; j < pos[T[0]].size(); j++) {
test(pos, T, pos[T[0]][j], 1, count);
}
return count;
}
void test(vector<vector<int>> pos, string T, int value, int start, int & count) {
if(start == T.length()) {
count++;
return;
}
if(!pos[T[start]][0])
return;
for(int i = 0; i < pos[T[start]].size(); i++) {
if(pos[T[start]][i] > value)
test(pos, T, pos[T[start]][i], start+1, count);
}
}
};
结果超时。尝试改进。
改进了一下,不用vector<vector<int>>保存S,直接递归,超时在更长的序列上了:
class Solution {
public:
int numDistinct(string S, string T) {
if(!S.length() or !T.length())
return 0;
int count = 0;
for(int j = 0; j < S.length(); j++) {
if(S[j] == T[0]) {
test(S, T, j, 1, count);
}
}
return count;
}
void test(string &S, string &T, int j, int i, int & count) {
if(i == T.length()) {
count++;
return;
}
for(int k = 0; k < S.length(); k++) {
if(S[k] == T[i])
if(k > j)
test(S, T, k, i+1, count);
}
}
};
网上学来动态规划法,递推公式为:
matrix[x][y] = (S[y] == T[x] ? matrix[x-1][y-1] : 0) + matrix[x][y-1]
边界值为 matrix[0][0] = 1, matrix[0][i] = 1, matrix[j][0] = 0。
class Solution {
public:
int numDistinct(string S, string T) {
int** matrix = new int*[T.length()+1];
for(int i = 0; i <= T.length(); i++)
matrix[i] = new int[S.length()+1];
for(int j = 0; j <= S.length(); j++) {
matrix[0][j] = 1;
}
for(int k = 1; k <= T.length(); k++) {
matrix[k][0] = 0;
}
for(int x = 1; x <= T.length(); x++) {
for(int y = 1; y <= S.length(); y++) {
matrix[x][y] = (T[x-1] == S[y-1] ? matrix[x-1][y-1] : 0) + matrix[x][y-1];
}
}
return matrix[T.length()][S.length()];
}
};
Java版:
public class Solution {
public int numDistinct(String S, String T) {
int[][] temp = new int[T.length()+1][S.length()+1];
for(int i = 0; i <= T.length(); i++) {
for(int j = 0; j <= S.length(); j++) {
if(i == 0)
temp[i][j] = 1;
else
if(j == 0)
temp[i][j] = 0;
else
temp[i][j] = ((T.charAt(i-1) == S.charAt(j-1)) ? temp[i-1][j-1] : 0) + temp[i][j-1];
}
}
return temp[T.length()][S.length()];
}
}
Python版:
class Solution:
# @return an integer
def numDistinct(self, S, T):
mat = []
for i in range(0, len(T)+1):
if i == 0:
temp = [1] * (len(S)+1)
else:
temp = [0] * (len(S)+1)
mat.append(temp)
for j in range(1, len(T)+1):
for k in range(1, len(S)+1):
mat[j][k] = (mat[j-1][k-1] if T[j-1] == S[k-1] else 0) + mat[j][k-1]
return mat[len(T)][len(S)]