Count Substrings with Number of 0s and 1s in Ratio of X : Y


In this problem, we will count substrings of the given binary string containing the number of ‘0’ and ‘1’ characters in the X : Y ratio.

The naïve approach finds all substrings of the given binary string, counts ‘0’ and ‘1’, and checks whether the counts are in the X : Y ratio. The efficient approach uses the prefix sum technique to solve the problem.

Problem statement − We have given a binary string of length bin_len. We need to count substrings having a number of 0s and 1s in the ratio of X : Y.

Sample examples

Input

bin_str = "00111001100"; X = 2; Y = 3;

Output

5

Explanation − The substrings having ‘1’ and ‘0’ in the 2 : 3 ratio are 00111, 01110, 10011, 11001, and 11100.

Input

bin_str = "11111"; X = 2; Y = 3;

Output

0

Explanation − The binary string contains only ‘1’. So, it is not possible to find a substring containing the ‘0’ and ‘1’ in the 2 : 3 ratio.

Input

bin_str = "00100"; X = 2; Y = 1;

Output

3

Explanation − We can take the 001, 010, and 100 substrings.

Approach 1

In this approach, we will use two nested loops to find all substrings of the binary string. After that, we will count the number of ‘1’ and ‘0’ in the binary string.

If the below condition is true for any substring, we can consider the substring in the answer.

zeroCnt * Y == oneCnt * X

Algorithm

Step 1 − Initialize the ‘ans’ with 0 to store the count of substrings.

Step 2 − Start traversing the binary string using the for loop. Also, use another loop to get each substring starting from the current index.

Step 3 − Use the substr() method to get the substring of the particular length.

Step 4 − Initialize the ‘zeroCnt’ and ‘oneCnt’ with 0 to store the count of ‘1’ and ‘0’ in the substring.

Step 5 − Use the third nested loop to count ‘1’ and ‘0’. If the current character is ‘1’, increment ‘oneCnt’. Otherwise, increment the ‘ZeroCnt’.

Step 6 − In the second nested loop, if zeroCnt * Y == oneCnt * X is true, increment the ‘ans’ value by 1.

Step 7 − At last, return the ‘ans’ value from the function.

Example

#include <bits/stdc++.h>
using namespace std;

int subStrCnt(string &bin_str, int X, int Y) {
    int ans = 0;
    // Get all substrings of the binary string
    for (int p = 0; p < bin_str.length(); p++) {
        for (int q = 1; q <= bin_str.length() - p; q++) {
            string sub_str = bin_str.substr(p, q);
            // Counting the number of zeros and ones in the substring
            int zeroCnt = 0, oneCnt = 0;
            for (int p = 0; p < sub_str.length(); p++) {
                if (sub_str[p] == '0')
                    zeroCnt++;
                else
                    oneCnt++;
            }
            // Checking whether the count of zeros and ones in the X:Y ratio
            if (zeroCnt * Y == oneCnt * X)
                ans++;
        }
    }
    return ans;
}
int main() {
    string bin_str = "00111001100";
    int X = 2;
    int Y = 3;
    cout << "The total substrings having 0's and 1's in the ratio X:Y is " << subStrCnt(bin_str, X, Y);
    return 0;
}

Output

The total substrings having 0's and 1's in the ratio X:Y is 5

Time complexity − O(N*N*N), where O(N*N) is to get all substrings and O(N) is to count ‘1’ and ‘0’ in the substring.

Space complexity − O(N) to store the substring.

Approach 2

We will consider the ‘0’ as −Y and ‘1’ as −X in this approach. We will find the sum of −Y and X according to the ‘0’ and ‘1’ numbers. If the sum is equal to 0, we can say that we found the valid substring.

Also, we will use the map data structure to store the prefix sum. Whenever we find any prefix sum value for a second time, we can take the substring between the indexes where the sum is 0.

For example, the binary string is "00111001100". We find the same prefix sum at the 0th and 5th index. So, we can take substring starting from the 1st index to the 5th index.

Algorithm

Step 1 − Initialize the ‘binary’ list to convert the binary string in the −Y and X format.

Step 2 − Traverse the string. If the current character is ‘0’, insert the ‘−Y’ in the list. Otherwise, insert the ‘X’ in the list.

Step 3 − Define the ‘pref’ map to store the prefix sum as a key and the number of occurrences of its value.

Step 4 − Also, initialize the ‘ans’ to store the count of substrings and ‘sum’ with 0 to store the prefix sum.

Step 5 − Start traversing the string. Add binary[p] to the sum.

Step 6 − If ‘sum’ is 0, increment the ‘ans’ by 1.

Step 7 − If the sum key exists in the map, add its value to the ‘ans’.

Step 8 − Increment the pref[sum] by 1.

Step 9 − Return the ‘ans’ value.

Example

#include <bits/stdc++.h>
using namespace std;

int subStrCnt(string &bin_str, int X, int Y) {
    vector<int> binary;
    for (auto ch : bin_str) {
        if (ch == '0') { 
            // Change '0' to -Y
            binary.push_back(-Y);
        } else { 
            // Change '1' to X
            binary.push_back(X);
        }
    }
    // To store prefix sum
    unordered_map<int, int> pref;
    int ans = 0;
    int sum = 0;
    // Traverse string
    for (int p = 0; p < binary.size(); p++) {
        // Add a current element to sum
        sum += binary[p];
        // When aX - bY = 0, we found the substring
        if (sum == 0)
            ans += 1;
        // When prefix sum exists, we add the value to ans
        if (pref.find(sum) != pref.end())
            ans += pref[sum];
        // Increment the count of prefix sum
        pref[sum] += 1;
    }
    return ans;
}
int main() {
    string bin_str = "00111001100";
    int X = 2;
    int Y = 3;
    cout << "The total substrings having 0's and 1's in the ratio X:Y is " << subStrCnt(bin_str, X, Y);
    return 0;
}

Output

The total substrings having 0's and 1's in the ratio X:Y is 5

Time complexity − O(N) for finding the prefix sum.

Space complexity − O(N) to store the prefix sum in the map.

The optimized approach efficiently solves the problem, taking only O(N) times. However, it can take more space for the large size of the binary string. Programmers may try to solve the problem to find the substring having an equal number of ‘0’ and ‘1’ in the binary string.

Updated on: 17-Jul-2023

155 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements