[
dp
string
]
Leetcode 1987 Number of Unique Good Subsequences
Problem statement
https://leetcode.com/problems/number-of-unique-good-subsequences/
Solution
This problem is very similar to problem 940. Distinct Subsequences II, so if you already solved or at least have seen it, it will help a lot. The idea is to use dp, where dp[i] is number of unique subsequences for string S[0], ... S[i] - which do not start with 0 (we will deal with 0 case in the end). Then, each time we add symbol we need to do the following:
- Imagine that we have
t1, t2, ..., tkunique subsequences fori-1. We also have optionst1 + S[i], t2 + S[i], ..., tk + S[i]. - However some of strings are the same, exactly for this we keep dictionary
last: is the last place for each symbol so far. So, we subtractdp[last[x]]number of options. - Also if we meet symbol
0for the first time, we need to subtract1.
Let us go through example S = 111000101 and see what what options we have:
dp[0] = 1, we have only one option: empty string"".- Consider next symbol:
1, we have"", 1,dp[1] = 2. - Consider next symbol:
1. We need to double number of options: we have4of them:"", 1and1, 11but one of them is repetition, it isdp[last[1]], so we have options"", 1, 11anddp[3] = 3. - Similarly
dp[4] = 4and we have options"", 1, 11, 111. - Now we have element
0and we meet it for the first time, so we have"", 1, 11, 111,0, 10, 110, 1110. We need to remove option0at the moment, so we have"", 1, 11, 111, 10, 110, 1110anddp[5] = 7. - Now we have again element
0. We meet it not for the first time, so we have previous options"", 1, 11, 111, 10, 110, 1110, new options are0, 10, 110, 1110, 100, 1100, 11100. How many of this options are intersect: it is10, 110, 1110and also we need to remove “0”, so optoins we are not happy with is0, 10, 110, 1110, which is exaclty what we had on step4but with added0. - I think you understand the logic now and can continue this for the rest of the string: I leave it to you as exercise, put your solutions in comments :)
In the end we need to deal with 0 case: we need to subtract -1 for empty set and add int("0" in S) to check if we have 0 in our string.
Complexity
Time complexity is O(n), space complexity also O(n).
Code
class Solution:
def numberOfUniqueGoodSubsequences(self, S):
dp, last = [1], {}
for i, x in enumerate(S):
dp.append(dp[-1] * 2)
dp[-1] -= dp[last[x]] if x in last else int(x == "0")
dp[-1] = dp[-1] % (10**9 + 7)
last[x] = i
return dp[-1] - 1 + int("0" in S)