LeetCode 115. 不同的子序列
博客好久没更新了orz…
题目链接
官方给的做法是用动态规划,不过我用的玄学做法也做对了
代码如下:
class Solution {
public:
map<char, set<int> > letter;
vector<set<int> > dict;
long long place[1005], sum[1005] = { 0 };
int numDistinct(string s, string t) {
int lens = s.length();
int lent = t.length();
for (int i = 0; i < lens; i++) {
letter[s[i]].insert(i);
}
for (int i = 0; i < lent; i++) {
dict.emplace_back(letter[t[i]]);
}
for (int i = lent - 1; i >= 0; i--) {
if (i == lent-1) {
for (auto wh : dict[i]) {
place[wh] = 1;
}
} else {
for (auto wh : dict[i]) {
place[wh] = sum[wh];
}
}
for (int j = lens - 2; j >= 0; j--) {
sum[j] = sum[j + 1] + (dict[i].count(j + 1) ? place[j + 1] : 0);
}
}
long long ans = 0;
for (auto e : dict[0]) {
ans += place[e];
}
return ans;
}
};
思路
首先找出t中每个字符在s中出现的位置,存到dict里面。
然后对于t,从最后一位开始往前倒序地考虑【从这一位开始,到最后一位,这部分子串】出现在s中的位置有几种可能
最后把所有的可能性累加在一起,就是最终的答案
在累加的过程中,使用sum数组记录后缀和,减少重复计算
第一次提交sum数组爆int了,改成long long就过了
用两组例子来解释一下
第一组样例:s = “babgbag”, t = “bag”
part1:t中的每个字符可能出现在s中的位置(0-6是s的index)
b 0 2 4
a 1 5
g 3 6
dict[0] = {0, 2, 4}
dict[1] = {1, 5}
dict[2] = {3, 6}
part2:考虑组合的可能性
g: (g出现在位置3有1种可能,位置6有一种可能)
place[3] = 1
place[6] = 1
ag: (ag出现在位置1有[1-3]和[1-6] 2种可能,以此类推)
place[1] = place[3] + place[6] = 2
place[5] = place[6] = 1
bag:
place[0] = place[1] + place[5] = 3
place[2] = place[5] = 1
place[4] = place[5] = 1
最后answer = 3+1+1 = 5
第二组样例:s = “rabbbat”, t = “rabbat”
part1:
r 0
a 1 5
b 2 3 4
b 2 3 4
a 1 5
t 6
dict[0] = {0}
dict[1] = {1, 5}
dict[2] = {2, 3, 4}
dict[3] = {2, 3, 4}
dict[4] = {1, 5}
dict[5] = {6}
part2:
t:
place[6] = 1
at:
place[1] = place[6] = 1
place[5] = place[6] = 1
bat:
place[2] = place[5] = 1
place[3] = place[5] = 1
place[4] = place[5] = 1
bbat:
(需要注意,更新place的时候,要从前往后更新。先更新place[4]=0再更新place[3]=place[4]的话数据就被覆盖掉了)
place[2] = place[3+4] = 2
place[3] = place[4] = 1
place[4] = 0
abbat:
place[1] = place[2+3+4] = 3
place[5] = 0
rabbat:
place[0] = place[1+5] = 3
最后answer = 3


发表评论