Count ways to split a Binary String into three substrings having equal count of zeros - GeeksforGeeks

14 Jun, 2021
Given binary string str, the task is to count the total number of ways to split the given string into three non-overlapping substrings having the same number of 0s.
Examples:
Input: str = “01010” Output: 4 Explanation: The possible splits are: [0, 10, 10], [01, 01, 0], [01, 0, 10], [0, 101, 0]
Input: str = “11111” Output: 0
Approach: To solve the problem, the idea is to use the concept of Hashing. Below are the steps to solve the problem:
Iterate over the string and count the total number of zeros and store it in a variable, say total_count.Use a Hashmap, say map, to store the frequency of cumulative sum of 0s.Initialize a variable k with total_count/3 which denotes the number of 0 required in each partition.Initialize variables res and sum to store the number of ways to split the string and cumulative sum of 0s respectively.Iterate over the given string and increment sum, if the current character is 0.Increment res by map[k], if sum = 2k and k exist on the map.Update the frequency of the sum in the map.Return res at the end.Return 0, if total_count is not divisible by 3.
Iterate over the string and count the total number of zeros and store it in a variable, say total_count.
Use a Hashmap, say map, to store the frequency of cumulative sum of 0s.
Initialize a variable k with total_count/3 which denotes the number of 0 required in each partition.
Initialize variables res and sum to store the number of ways to split the string and cumulative sum of 0s respectively.
Iterate over the given string and increment sum, if the current character is 0.
Increment res by map[k], if sum = 2k and k exist on the map.
Update the frequency of the sum in the map.
Return res at the end.
Return 0, if total_count is not divisible by 3.
Below is the implementation of the above approach:
C++
Java
Python3
C#
Javascript
// C++ implementation for the above approach#include<bits/stdc++.h>using namespace std; // Function to return ways to split// a string into three  parts// with the equal number of 0int count(string s){         // Store total count of 0s    int cnt = 0;     // Count total no. of 0s    // character in given string    for(char c : s)    {        cnt += c == '0' ? 1 : 0;    }     // If total count of 0    // character is not    // divisible by 3    if (cnt % 3 != 0)        return 0;     int res = 0, k = cnt / 3, sum = 0;     // Initialize mp to store    // frequency of k    map<int, int> mp;     // Traverse string to find    // ways to split string    for(int i = 0; i < s.length(); i++)    {                 // Increment count if 0 appears        sum += s[i] == '0' ? 1 : 0;         // Increment result if sum equal to        // 2*k and k exists in mp        if (sum == 2 * k && mp.find(k) != mp.end() &&            i < s.length() - 1 && i > 0)        {            res += mp[k];        }                 // Insert sum in mp        mp[sum]++;    }         // Return result    return res;} // Driver Codeint main(){         // Given string    string str = "01010";      // Function call    cout << count(str);} // This code is contributed by rutvik_56
// Java implementation for the above approach import java.util.*;import java.lang.*; class GFG {     // Function to return ways to split    // a string into three  parts    // with the equal number of 0    static int count(String s)    {        // Store total count of 0s        int cnt = 0;         // Count total no. of 0s        // character in given string        for (char c : s.toCharArray()) {            cnt += c == '0' ? 1 : 0;        }         // If total count of 0        // character is not        // divisible by 3        if (cnt % 3 != 0)            return 0;         int res = 0, k = cnt / 3, sum = 0;         // Initialize map to store        // frequency of k        Map<Integer, Integer> map = new HashMap<>();         // Traverse string to find        // ways to split string        for (int i = 0; i < s.length(); i++) {             // Increment count if 0 appears            sum += s.charAt(i) == '0' ? 1 : 0;             // Increment result if sum equal to            // 2*k and k exists in map            if (sum == 2 * k && map.containsKey(k)                && i < s.length() - 1 && i > 0) {                res += map.get(k);            }             // Insert sum in map            map.put(sum,                    map.getOrDefault(sum, 0) + 1);        }         // Return result        return res;    }    // Driver Code    public static void main(String[] args)    {        // Given string        String str = "01010";         // Function call        System.out.println(count(str));    }}
# Python3 implementation for# the above approach # Function to return ways to split# a string into three  parts# with the equal number of 0def count(s):     # Store total count of 0s    cnt = 0     # Count total no. of 0s    # character in given string    for c in s:        if c == '0':            cnt += 1     # If total count of 0    # character is not    # divisible by 3    if (cnt % 3 != 0):        return 0     res = 0    k = cnt // 3    sum = 0     # Initialize map to store    # frequency of k    mp = {}     # Traverse string to find    # ways to split string    for i in range(len(s)):         # Increment count if 0 appears        if s[i] == '0':            sum += 1         # Increment result if sum equal to        # 2*k and k exists in map        if (sum == 2 * k and k in mp and            i < len(s) - 1 and i > 0):            res += mp[k]         # Insert sum in map        if sum in mp:            mp[sum] += 1        else:            mp[sum] = 1                 # Return result    return res # Driver Codeif __name__ == "__main__":     # Given string    st = "01010"     # Function call    print(count(st))     # This code is contributed by Chitranayal
// C# implementation for the above approachusing System;using System.Collections.Generic; class GFG{ // Function to return ways to split// a string into three parts// with the equal number of 0static int count(String s){         // Store total count of 0s    int cnt = 0;     // Count total no. of 0s    // character in given string    foreach(char c in s.ToCharArray())    {        cnt += c == '0' ? 1 : 0;    }     // If total count of 0    // character is not    // divisible by 3    if (cnt % 3 != 0)        return 0;     int res = 0, k = cnt / 3, sum = 0;     // Initialize map to store    // frequency of k    Dictionary<int,               int> map = new Dictionary<int,                                         int>();     // Traverse string to find    // ways to split string    for(int i = 0; i < s.Length; i++)    {                 // Increment count if 0 appears        sum += s[i] == '0' ? 1 : 0;         // Increment result if sum equal to        // 2*k and k exists in map        if (sum == 2 * k && map.ContainsKey(k) &&            i < s.Length - 1 && i > 0)        {            res += map[k];        }         // Insert sum in map        if(map.ContainsKey(sum))            map[sum] = map[sum] + 1;        else            map.Add(sum, 1);    }     // Return result    return res;} // Driver Codepublic static void Main(String[] args){         // Given string    String str = "01010";     // Function call    Console.WriteLine(count(str));}} // This code is contributed by Amit Katiyar
<script> // Javascript implementation for the above approach // Function to return ways to split// a string into three  parts// with the equal number of 0function count(s){         // Store total count of 0s    var cnt = 0;     // Count total no. of 0s    // character in given string    s.split('').forEach(c => {             cnt += (c == '0') ? 1 : 0;    });     // If total count of 0    // character is not    // divisible by 3    if (cnt % 3 != 0)        return 0;     var res = 0, k = parseInt(cnt / 3), sum = 0;     // Initialize mp to store    // frequency of k    var mp = new Map();     // Traverse string to find    // ways to split string    for(var i = 0; i < s.length; i++)    {                 // Increment count if 0 appears        sum += (s[i] == '0') ? 1 : 0;         // Increment result if sum equal to        // 2*k and k exists in mp        if (sum == 2 * k && mp.has(k) &&            i < s.length - 1 && i > 0)        {            res += mp.get(k);        }                 // Insert sum in mp        if(mp.has(sum))            mp.set(sum, mp.get(sum)+1)        else            mp.set(sum, 1);    }         // Return result    return res;} // Driver Code// Given stringvar str = "01010"; // Function calldocument.write( count(str)); </script>
4
Time Complexity: O(N) Auxiliary Space: O(N)
EFFICIENT APPROACH:
In order to split the input string into three parts, only two cuts are needed, which will give three substrings-S1, S2, and S3. Each substring will have an equal number of 0’s and that will be (total number of 0’s)/3. Now keep track of the count of the number of 0’s from the beginning of the string. Once the count is equal to (total number of 0’s)/3, make the first cut. Similarly, make the second cut once the count of 0’s equals 2*(total number of 1’s)/3.
Algorithm
Count the number of 0’s. If not divisible by 3, then answer=0.If the count is 0 then each substring will have an equal number of ‘0’s i.e. zero number of ‘0’s. Therefore, the total number of ways to split the given string is the number of combinations of selecting 2 places to split the string out of n-1 places. For the first selection, we have n-1 choices and for the second selection, we have n-2 choices. Hence, the total number of combinations is (n-1)*(n-2). Since the selections are identical, therefore divide it by factorial of 2. So answer= ((n-1)*(n-2))/2.Traverse the given string from the beginning and keeping count of the number of ‘0s’ again, if the count reaches the (total number of ‘0s’)/3, we begin to accumulate the number of the ways of the 1st cut; when the count reaches the 2*(total number of ‘0s’)/3, we start to accumulate the number of the ways of the 2nd cut.The answer is the multiplication of the number of ways of the 1st cut and 2nd cut.
Count the number of 0’s. If not divisible by 3, then answer=0.
If the count is 0 then each substring will have an equal number of ‘0’s i.e. zero number of ‘0’s. Therefore, the total number of ways to split the given string is the number of combinations of selecting 2 places to split the string out of n-1 places. For the first selection, we have n-1 choices and for the second selection, we have n-2 choices. Hence, the total number of combinations is (n-1)*(n-2). Since the selections are identical, therefore divide it by factorial of 2. So answer= ((n-1)*(n-2))/2.
Traverse the given string from the beginning and keeping count of the number of ‘0s’ again, if the count reaches the (total number of ‘0s’)/3, we begin to accumulate the number of the ways of the 1st cut; when the count reaches the 2*(total number of ‘0s’)/3, we start to accumulate the number of the ways of the 2nd cut.
The answer is the multiplication of the number of ways of the 1st cut and 2nd cut.
Below is the implementation of the above approach:
C++
Java
Python3
C#
Javascript
// C++ program for above approach#include <bits/stdc++.h>using namespace std; // Function to calculate// the number of ways to splitint splitstring(string s){    int n = s.length();     // Calculating the total    // number of zeros    int zeros = 0;    for (int i = 0; i < n; i++)        if (s[i] == '0')            zeros++;     // Case1    // If total count of zeros is not    // divisible by 3    if (zeros % 3 != 0)        return 0;     // Case2    // if total count of zeros    // is zero    if (zeros == 0)        return ((n - 1) * (n - 2)) / 2;     // Case3    // General case     // Number of zeros in each substring    int zerosInEachSubstring = zeros / 3;     // Initialising zero to the number of ways    // for first and second cut    int waysOfFirstCut = 0, waysOfSecondCut = 0;     // Initializing the count    int count = 0;     // Traversing from the beginning    for (int i = 0; i < n; i++)    {                 // Incrementing the count        // if the element is '0'        if (s[i] == '0')            count++;         // Incrementing the ways for the        // 1st cut if count is equal to        // zeros required in each substring        if (count == zerosInEachSubstring)            waysOfFirstCut++;         // Incrementing the ways for the        // 2nd cut if count is equal to        // 2*(zeros required in each substring)        else if (count == 2 * zerosInEachSubstring)            waysOfSecondCut++;    }     // Total number of ways to split is    // multiplication of ways for the 1st    // and 2nd cut    return waysOfFirstCut * waysOfSecondCut;} // Driver Codeint main(){    string s = "01010";       // Function Call    cout << "The number of ways to split is "         << splitstring(s) << endl;} // this code is contributed by Arif
// Java program for above approachimport java.util.*; class GFG{     // Function to calculate// the number of ways to splitstatic int splitstring(String s){    int n = s.length();     // Calculating the total    // number of zeros    int zeros = 0;    for(int i = 0; i < n; i++)        if (s.charAt(i) == '0')            zeros++;     // Case1    // If total count of zeros is not    // divisible by 3    if (zeros % 3 != 0)        return 0;     // Case2    // if total count of zeros    // is zero    if (zeros == 0)        return ((n - 1) * (n - 2)) / 2;     // Case3    // General case     // Number of zeros in each substring    int zerosInEachSubstring = zeros / 3;     // Initialising zero to the number of ways    // for first and second cut    int waysOfFirstCut = 0;    int waysOfSecondCut = 0;     // Initializing the count    int count = 0;     // Traversing from the beginning    for(int i = 0; i < n; i++)    {                 // Incrementing the count        // if the element is '0'        if (s.charAt(i) == '0')            count++;         // Incrementing the ways for the        // 1st cut if count is equal to        // zeros required in each substring        if (count == zerosInEachSubstring)            waysOfFirstCut++;         // Incrementing the ways for the        // 2nd cut if count is equal to        // 2*(zeros required in each substring)        else if (count == 2 * zerosInEachSubstring)            waysOfSecondCut++;    }     // Total number of ways to split is    // multiplication of ways for the 1st    // and 2nd cut    return waysOfFirstCut * waysOfSecondCut;} // Driver Codepublic static void main(String args[]){    String s = "01010";     // Function Call    System.out.println("The number of " +                       "ways to split is " +                       splitstring(s));}} // This code is contributed by Stream_Cipher
# Python3 program for above approach # Function to calculate# the number of ways to splitdef splitstring(s):     n = len(s)     # Calculating the total    # number of zeros    zeros = 0    for i in range(n):        if s[i] == '0':            zeros += 1     # Case1    # If total count of zeros is not    # divisible by 3    if zeros % 3 != 0:        return 0     # Case2    # if total count of zeros    # is zero    if zeros == 0:        return ((n - 1) *                (n - 2)) // 2     # Case3    # General case     # Number of zeros in each substring    zerosInEachSubstring = zeros // 3     # Initialising zero to the number of ways    # for first and second cut    waysOfFirstCut, waysOfSecondCut = 0, 0     # Initializing the count    count = 0     # Traversing from the beginning    for i in range(n):                 # Incrementing the count        # if the element is '0'        if s[i] == '0':            count += 1         # Incrementing the ways for the        # 1st cut if count is equal to        # zeros required in each substring        if (count == zerosInEachSubstring):            waysOfFirstCut += 1         # Incrementing the ways for the        # 2nd cut if count is equal to        # 2*(zeros required in each substring)        elif (count == 2 * zerosInEachSubstring):            waysOfSecondCut += 1     # Total number of ways to split is    # multiplication of ways for the 1st    # and 2nd cut    return waysOfFirstCut * waysOfSecondCut # Driver codes = "01010" # Function callprint("The number of ways to split is", splitstring(s)) # This code is contributed by divyeshrabadiya07
// C# program for above approachusing System.Collections.Generic;using System; class GFG{     // Function to calculate// the number of ways to splitstatic int splitstring(string s){    int n = s.Length;     // Calculating the total    // number of zeros    int zeros = 0;    for(int i = 0; i < n; i++)        if (s[i] == '0')            zeros++;     // Case1    // If total count of zeros is not    // divisible by 3    if (zeros % 3 != 0)        return 0;     // Case2    // if total count of zeros    // is zero    if (zeros == 0)        return ((n - 1) * (n - 2)) / 2;     // Case3    // General case     // Number of zeros in each substring    int zerosInEachSubstring = zeros / 3;     // Initialising zero to the number of ways    // for first and second cut    int waysOfFirstCut = 0;    int waysOfSecondCut = 0;     // Initializing the count    int count = 0;     // Traversing from the beginning    for(int i = 0; i < n; i++)    {                 // Incrementing the count        // if the element is '0'        if (s[i] == '0')            count++;         // Incrementing the ways for the        // 1st cut if count is equal to        // zeros required in each substring        if (count == zerosInEachSubstring)            waysOfFirstCut++;         // Incrementing the ways for the        // 2nd cut if count is equal to        // 2*(zeros required in each substring)        else if (count == 2 * zerosInEachSubstring)            waysOfSecondCut++;    }     // Total number of ways to split is    // multiplication of ways for the 1st    // and 2nd cut    return waysOfFirstCut * waysOfSecondCut;} // Driver Codepublic static void Main(){    string s = "01010";     // Function call    Console.WriteLine("The number of ways " +                      "to split is " +                      splitstring(s));}} // This code is contributed by Stream_Cipher
<script>    // Javascript program for above approach         // Function to calculate    // the number of ways to split    function splitstring(s)    {        let n = s.length;         // Calculating the total        // number of zeros        let zeros = 0;        for(let i = 0; i < n; i++)            if (s[i] == '0')                zeros++;         // Case1        // If total count of zeros is not        // divisible by 3        if (zeros % 3 != 0)            return 0;         // Case2        // if total count of zeros        // is zero        if (zeros == 0)            return parseInt(((n - 1) * (n - 2)) / 2, 10);         // Case3        // General case         // Number of zeros in each substring        let zerosInEachSubstring = parseInt(zeros / 3, 10);         // Initialising zero to the number of ways        // for first and second cut        let waysOfFirstCut = 0;        let waysOfSecondCut = 0;         // Initializing the count        let count = 0;         // Traversing from the beginning        for(let i = 0; i < n; i++)        {             // Incrementing the count            // if the element is '0'            if (s[i] == '0')                count++;             // Incrementing the ways for the            // 1st cut if count is equal to            // zeros required in each substring            if (count == zerosInEachSubstring)                waysOfFirstCut++;             // Incrementing the ways for the            // 2nd cut if count is equal to            // 2*(zeros required in each substring)            else if (count == 2 * zerosInEachSubstring)                waysOfSecondCut++;        }         // Total number of ways to split is        // multiplication of ways for the 1st        // and 2nd cut        return waysOfFirstCut * waysOfSecondCut;    }         let s = "01010";      // Function call    document.write("The number of ways " +                      "to split is " +                      splitstring(s)); </script>
The number of ways to split is 4
Time Complexity: O(n)
Space Complexity: O(1) 
amit143katiyar
ukasp
rutvik_56
ArifShaikh
Stream_Cipher
divyeshrabadiya07
surinderdawra388
importantly
rameshtravel07
binary-string
frequency-counting
substring
Hash
Mathematical
Searching
Strings
Searching
Hash
Strings
Mathematical
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Hashing | Set 2 (Separate Chaining)
Sort string of characters
Most frequent element in an array
Counting frequencies of array elements
Double Hashing
Program for Fibonacci numbers
Write a program to print all permutations of a given string
C++ Data Types
Set in C++ Standard Template Library (STL)
Coin Change | DP-7