Count ways to split a Binary String into three substrings having equal count of zeros
Last Updated :
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.
Below is the implementation of the above approach:
C++
#include<bits/stdc++.h>
using namespace std;
int count(string s)
{
int cnt = 0;
for ( char c : s)
{
cnt += c == '0' ? 1 : 0;
}
if (cnt % 3 != 0)
return 0;
int res = 0, k = cnt / 3, sum = 0;
map< int , int > mp;
for ( int i = 0; i < s.length(); i++)
{
sum += s[i] == '0' ? 1 : 0;
if (sum == 2 * k && mp.find(k) != mp.end() &&
i < s.length() - 1 && i > 0)
{
res += mp[k];
}
mp[sum]++;
}
return res;
}
int main()
{
string str = "01010" ;
cout << count(str);
}
|
Java
import java.util.*;
import java.lang.*;
class GFG {
static int count(String s)
{
int cnt = 0 ;
for ( char c : s.toCharArray()) {
cnt += c == '0' ? 1 : 0 ;
}
if (cnt % 3 != 0 )
return 0 ;
int res = 0 , k = cnt / 3 , sum = 0 ;
Map<Integer, Integer> map = new HashMap<>();
for ( int i = 0 ; i < s.length(); i++) {
sum += s.charAt(i) == '0' ? 1 : 0 ;
if (sum == 2 * k && map.containsKey(k)
&& i < s.length() - 1 && i > 0 ) {
res += map.get(k);
}
map.put(sum,
map.getOrDefault(sum, 0 ) + 1 );
}
return res;
}
public static void main(String[] args)
{
String str = "01010" ;
System.out.println(count(str));
}
}
|
Python3
def count(s):
cnt = 0
for c in s:
if c = = '0' :
cnt + = 1
if (cnt % 3 ! = 0 ):
return 0
res = 0
k = cnt / / 3
sum = 0
mp = {}
for i in range ( len (s)):
if s[i] = = '0' :
sum + = 1
if ( sum = = 2 * k and k in mp and
i < len (s) - 1 and i > 0 ):
res + = mp[k]
if sum in mp:
mp[ sum ] + = 1
else :
mp[ sum ] = 1
return res
if __name__ = = "__main__" :
st = "01010"
print (count(st))
|
C#
using System;
using System.Collections.Generic;
class GFG{
static int count(String s)
{
int cnt = 0;
foreach ( char c in s.ToCharArray())
{
cnt += c == '0' ? 1 : 0;
}
if (cnt % 3 != 0)
return 0;
int res = 0, k = cnt / 3, sum = 0;
Dictionary< int ,
int > map = new Dictionary< int ,
int >();
for ( int i = 0; i < s.Length; i++)
{
sum += s[i] == '0' ? 1 : 0;
if (sum == 2 * k && map.ContainsKey(k) &&
i < s.Length - 1 && i > 0)
{
res += map[k];
}
if (map.ContainsKey(sum))
map[sum] = map[sum] + 1;
else
map.Add(sum, 1);
}
return res;
}
public static void Main(String[] args)
{
String str = "01010" ;
Console.WriteLine(count(str));
}
}
|
Javascript
<script>
function count(s)
{
var cnt = 0;
s.split( '' ).forEach(c => {
cnt += (c == '0' ) ? 1 : 0;
});
if (cnt % 3 != 0)
return 0;
var res = 0, k = parseInt(cnt / 3), sum = 0;
var mp = new Map();
for ( var i = 0; i < s.length; i++)
{
sum += (s[i] == '0' ) ? 1 : 0;
if (sum == 2 * k && mp.has(k) &&
i < s.length - 1 && i > 0)
{
res += mp.get(k);
}
if (mp.has(sum))
mp.set(sum, mp.get(sum)+1)
else
mp.set(sum, 1);
}
return res;
}
var str = "01010" ;
document.write( count(str));
</script>
|
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.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int splitstring(string s)
{
int n = s.length();
int zeros = 0;
for ( int i = 0; i < n; i++)
if (s[i] == '0' )
zeros++;
if (zeros % 3 != 0)
return 0;
if (zeros == 0)
return ((n - 1) * (n - 2)) / 2;
int zerosInEachSubstring = zeros / 3;
int waysOfFirstCut = 0, waysOfSecondCut = 0;
int count = 0;
for ( int i = 0; i < n; i++)
{
if (s[i] == '0' )
count++;
if (count == zerosInEachSubstring)
waysOfFirstCut++;
else if (count == 2 * zerosInEachSubstring)
waysOfSecondCut++;
}
return waysOfFirstCut * waysOfSecondCut;
}
int main()
{
string s = "01010" ;
cout << "The number of ways to split is "
<< splitstring(s) << endl;
}
|
Java
import java.util.*;
class GFG{
static int splitstring(String s)
{
int n = s.length();
int zeros = 0 ;
for ( int i = 0 ; i < n; i++)
if (s.charAt(i) == '0' )
zeros++;
if (zeros % 3 != 0 )
return 0 ;
if (zeros == 0 )
return ((n - 1 ) * (n - 2 )) / 2 ;
int zerosInEachSubstring = zeros / 3 ;
int waysOfFirstCut = 0 ;
int waysOfSecondCut = 0 ;
int count = 0 ;
for ( int i = 0 ; i < n; i++)
{
if (s.charAt(i) == '0' )
count++;
if (count == zerosInEachSubstring)
waysOfFirstCut++;
else if (count == 2 * zerosInEachSubstring)
waysOfSecondCut++;
}
return waysOfFirstCut * waysOfSecondCut;
}
public static void main(String args[])
{
String s = "01010" ;
System.out.println( "The number of " +
"ways to split is " +
splitstring(s));
}
}
|
Python3
def splitstring(s):
n = len (s)
zeros = 0
for i in range (n):
if s[i] = = '0' :
zeros + = 1
if zeros % 3 ! = 0 :
return 0
if zeros = = 0 :
return ((n - 1 ) *
(n - 2 )) / / 2
zerosInEachSubstring = zeros / / 3
waysOfFirstCut, waysOfSecondCut = 0 , 0
count = 0
for i in range (n):
if s[i] = = '0' :
count + = 1
if (count = = zerosInEachSubstring):
waysOfFirstCut + = 1
elif (count = = 2 * zerosInEachSubstring):
waysOfSecondCut + = 1
return waysOfFirstCut * waysOfSecondCut
s = "01010"
print ( "The number of ways to split is" , splitstring(s))
|
C#
using System.Collections.Generic;
using System;
class GFG{
static int splitstring( string s)
{
int n = s.Length;
int zeros = 0;
for ( int i = 0; i < n; i++)
if (s[i] == '0' )
zeros++;
if (zeros % 3 != 0)
return 0;
if (zeros == 0)
return ((n - 1) * (n - 2)) / 2;
int zerosInEachSubstring = zeros / 3;
int waysOfFirstCut = 0;
int waysOfSecondCut = 0;
int count = 0;
for ( int i = 0; i < n; i++)
{
if (s[i] == '0' )
count++;
if (count == zerosInEachSubstring)
waysOfFirstCut++;
else if (count == 2 * zerosInEachSubstring)
waysOfSecondCut++;
}
return waysOfFirstCut * waysOfSecondCut;
}
public static void Main()
{
string s = "01010" ;
Console.WriteLine( "The number of ways " +
"to split is " +
splitstring(s));
}
}
|
Javascript
<script>
function splitstring(s)
{
let n = s.length;
let zeros = 0;
for (let i = 0; i < n; i++)
if (s[i] == '0' )
zeros++;
if (zeros % 3 != 0)
return 0;
if (zeros == 0)
return parseInt(((n - 1) * (n - 2)) / 2, 10);
let zerosInEachSubstring = parseInt(zeros / 3, 10);
let waysOfFirstCut = 0;
let waysOfSecondCut = 0;
let count = 0;
for (let i = 0; i < n; i++)
{
if (s[i] == '0' )
count++;
if (count == zerosInEachSubstring)
waysOfFirstCut++;
else if (count == 2 * zerosInEachSubstring)
waysOfSecondCut++;
}
return waysOfFirstCut * waysOfSecondCut;
}
let s = "01010" ;
document.write( "The number of ways " +
"to split is " +
splitstring(s));
</script>
|
Output
The number of ways to split is 4
Time Complexity: O(n)
Space Complexity: O(1)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...