{x}
blog image

Number of Unique Good Subsequences

You are given a binary string binary. A subsequence of binary is considered good if it is not empty and has no leading zeros (with the exception of "0").

Find the number of unique good subsequences of binary.

  • For example, if binary = "001", then all the good subsequences are ["0", "0", "1"], so the unique good subsequences are "0" and "1". Note that subsequences "00", "01", and "001" are not good because they have leading zeros.

Return the number of unique good subsequences of binary. Since the answer may be very large, return it modulo 109 + 7.

A subsequence is a sequence that can be derived from another sequence by deleting some or no elements without changing the order of the remaining elements.

 

Example 1:

Input: binary = "001"
Output: 2
Explanation: The good subsequences of binary are ["0", "0", "1"].
The unique good subsequences are "0" and "1".

Example 2:

Input: binary = "11"
Output: 2
Explanation: The good subsequences of binary are ["1", "1", "11"].
The unique good subsequences are "1" and "11".

Example 3:

Input: binary = "101"
Output: 5
Explanation: The good subsequences of binary are ["1", "0", "1", "10", "11", "101"]. 
The unique good subsequences are "0", "1", "10", "11", and "101".

 

Constraints:

  • 1 <= binary.length <= 105
  • binary consists of only '0's and '1's.

Solution Explanation: Dynamic Programming Approach

This problem can be efficiently solved using dynamic programming. The core idea is to track the count of unique good subsequences ending in '1' and '0' separately. We maintain two variables:

  • f: Represents the count of unique good subsequences ending with '1'.
  • g: Represents the count of unique good subsequences ending with '0' and having at least one '1' before the trailing '0'. This condition ensures we avoid counting subsequences with leading zeros (except for "0" itself).

We iterate through the input string binary. For each character:

  • If the character is '0': We can extend all existing subsequences ending in '1' (f) by appending '0'. Additionally, if we encounter a '0' the only possible good subsequence will be '0' hence setting ans =1. We also update g accordingly.
  • If the character is '1': We can extend all subsequences ending in '1' (f), all subsequences ending in '0' (g), and we can also have a new subsequence consisting of only '1'. Therefore, we update f.

Finally, the total number of unique good subsequences is the sum of f, g, and a potential additional 1 (to account for the subsequence "0" if a '0' exists in the string).

Time and Space Complexity

  • Time Complexity: O(n), where n is the length of the binary string. We iterate through the string once.
  • Space Complexity: O(1). We use only a constant number of variables to store the counts.

Code Implementation (Python)

class Solution:
    def numberOfUniqueGoodSubsequences(self, binary: str) -> int:
        f = g = 0
        ans = 0
        mod = 10**9 + 7
        for c in binary:
            if c == "0":
                g = (g + f) % mod
                ans = 1 # handle the case where only '0' is present
            else:
                f = (f + g + 1) % mod
        ans = (ans + f + g) % mod # add f and g and handle the case when '0' is present
        return ans
 

Code Implementation (Java)

class Solution {
    public int numberOfUniqueGoodSubsequences(String binary) {
        final int mod = (int) 1e9 + 7;
        int f = 0, g = 0;
        int ans = 0;
        for (int i = 0; i < binary.length(); ++i) {
            if (binary.charAt(i) == '0') {
                g = (g + f) % mod;
                ans = 1;
            } else {
                f = (f + g + 1) % mod;
            }
        }
        ans = (ans + f + g) % mod;
        return ans;
    }
}

The implementations in other languages (C++, Go, TypeScript) follow a very similar structure, adapting the syntax to their respective languages while maintaining the same algorithmic logic. The key is the use of f and g to track the counts and the modulo operation to handle potential integer overflow.