Given a binary string S consisting of only 0’s and 1’s. Count the number of substrings of this string such that the length of the substring is divisible by the number of 1’s in the substring.
Examples:
Input: S = “01010”
Output: 10Input: S = “1111100000”
Output: 25
Naive Approach:
- Iterate through all the substrings and for each substring count the number of 1’s. If the length of the substring is divisible by the count of 1’s, then increase the count. This approach will take O(N3) time.
- To make the solution more efficient, instead of traversing the entire substring to count the number of 1’s in it, we can use Prefix Sum Array.
number of 1’s in the substring [l: r] = prefix_sum[r] – prefix_sum[l – 1]
Below is the implementation of the above approach.
// C++ program to count number of // substring under given condition #include <bits/stdc++.h> using namespace std;
// Function return count of // such substring int countOfSubstrings(string s)
{ int n = s.length();
int prefix_sum[n] = { 0 };
// Mark 1 at those indices
// where '1' appears
for ( int i = 0; i < n; i++) {
if (s[i] == '1' )
prefix_sum[i] = 1;
}
// Take prefix sum
for ( int i = 1; i < n; i++)
prefix_sum[i] += prefix_sum[i - 1];
int answer = 0;
// Iterate through all the
// substrings
for ( int i = 0; i < n; i++) {
for ( int j = i; j < n; j++) {
int countOfOnes = prefix_sum[j]
- (i - 1 >= 0 ?
prefix_sum[i - 1] : 0);
int length = j - i + 1;
if (countOfOnes > 0 &&
length % countOfOnes == 0)
answer++;
}
}
return answer;
} // Driver Code int main()
{ string S = "1111100000" ;
cout << countOfSubstrings(S);
return 0;
} |
// Java program to count number of // subString under given condition import java.util.*;
class GFG{
// Function return count of // such substring static int countOfSubStrings(String s)
{ int n = s.length();
int []prefix_sum = new int [n];
// Mark 1 at those indices
// where '1' appears
for ( int i = 0 ; i < n; i++) {
if (s.charAt(i) == '1' )
prefix_sum[i] = 1 ;
}
// Take prefix sum
for ( int i = 1 ; i < n; i++)
prefix_sum[i] += prefix_sum[i - 1 ];
int answer = 0 ;
// Iterate through all the
// subStrings
for ( int i = 0 ; i < n; i++) {
for ( int j = i; j < n; j++) {
int countOfOnes = prefix_sum[j]
- (i - 1 >= 0 ?
prefix_sum[i - 1 ] : 0 );
int length = j - i + 1 ;
if (countOfOnes > 0 &&
length % countOfOnes == 0 )
answer++;
}
}
return answer;
} // Driver Code public static void main(String[] args)
{ String S = "1111100000" ;
System.out.print(countOfSubStrings(S));
} } // This code contributed by sapnasingh4991 |
# Python3 program to count number of # substring under given condition # Function return count of # such substring def countOfSubstrings(s):
n = len (s)
prefix_sum = [ 0 for i in range (n)]
# Mark 1 at those indices
# where '1' appears
for i in range (n):
if (s[i] = = '1' ):
prefix_sum[i] = 1
# Take prefix sum
for i in range ( 1 , n, 1 ):
prefix_sum[i] + = prefix_sum[i - 1 ]
answer = 0
# Iterate through all the
# substrings
for i in range (n):
for j in range (i, n, 1 ):
if (i - 1 > = 0 ):
countOfOnes = prefix_sum[j] - prefix_sum[i - 1 ]
else :
countOfOnes = prefix_sum[j]
length = j - i + 1
if (countOfOnes > 0 and length % countOfOnes = = 0 ):
answer + = 1
return answer
# Driver Code if __name__ = = '__main__' :
S = "1111100000"
print (countOfSubstrings(S))
# This code is contributed by Bhupendra_Singh |
// C# program to count number of // subString under given condition using System;
class GFG{
// Function return count of // such substring static int countOfSubStrings(String s)
{ int n = s.Length;
int []prefix_sum = new int [n];
// Mark 1 at those indices
// where '1' appears
for ( int i = 0; i < n; i++)
{
if (s[i] == '1' )
prefix_sum[i] = 1;
}
// Take prefix sum
for ( int i = 1; i < n; i++)
prefix_sum[i] += prefix_sum[i - 1];
int answer = 0;
// Iterate through all the
// subStrings
for ( int i = 0; i < n; i++)
{
for ( int j = i; j < n; j++)
{
int countOfOnes = prefix_sum[j] -
(i - 1 >= 0 ?
prefix_sum[i - 1] : 0);
int length = j - i + 1;
if (countOfOnes > 0 &&
length % countOfOnes == 0)
answer++;
}
}
return answer;
} // Driver Code public static void Main(String[] args)
{ String S = "1111100000" ;
Console.Write(countOfSubStrings(S));
} } // This code is contributed by Rohit_ranjan |
<script> // Javascript program to count number of // subString under given condition // Function return count of // such substring function countOfSubStrings(s)
{ let n = s.length;
let prefix_sum = Array.from({length: n}, (_, i) => 0);
// Mark 1 at those indices
// where '1' appears
for (let i = 0; i < n; i++) {
if (s[i] == '1' )
prefix_sum[i] = 1;
}
// Take prefix sum
for (let i = 1; i < n; i++)
prefix_sum[i] += prefix_sum[i - 1];
let answer = 0;
// Iterate through all the
// subStrings
for (let i = 0; i < n; i++) {
for (let j = i; j < n; j++) {
let countOfOnes = prefix_sum[j]
- (i - 1 >= 0 ?
prefix_sum[i - 1] : 0);
let length = j - i + 1;
if (countOfOnes > 0 &&
length % countOfOnes == 0)
answer++;
}
}
return answer;
} // Driver Code let S = "1111100000" ;
document.write(countOfSubStrings(S));
</script> |
Output:
25
Time Complexity: O(N2)
Auxiliary Space: O(N)
Efficient Approach:
- Let’s use the prefix sum array as discussed in the previous approach. Let’s take a substring [l: r] which follows the condition given, we can say that:
r – l + 1 = k * (prefix_sum[r] – prefix_sum[l-1]), where k is some integer
- This can also be written as:
r – k * prefix_sum[r] = l – 1 – k * prefix_sum[l-1]
Observing this equation, we can create another array of the B[i] = i – k * prefix_sum[i], for 0 <= k < n. So, the problem now is to calculate the number of pairs of equal integers in B for each k.
- Let’s take a fixed number x. If k > x, then as r – l + 1 <= n ( for any pair of l, r ), we get the following inequality :
prefix_sum[r] – prefix_sum[l-1] = (r – l + 1)/k <= n/x
- This goes on to show that the number of ones and k is not large in substrings satisfying the given conditions. (this is just for estimation of efficiency). Now for k <= x, we need to calculate the number of pairs of equal integers. The following inequality is satisfied here:
(-1) *n*x <= i – k – prefix_sum[i] <= n
- So, we can put all numbers into one array for each k independently and find the number of equal integers.
- The next step would be to fix values of l and iterate on the number of 1’s in the string, and for each value get the bounds for r. For a given count of the number of 1’s, we can evaluate which remainder will give r. The problem now becomes is to calculate the number of integers on some segments, which gives some fixed remainder (rem) when divided by some fixed integer. This calculation can be done in O(1). Also, note that it’s important to count only such r values for which k > x.
Below is the implementation of the above approach.
// C++ program to count number of // substring under given condition #include <bits/stdc++.h> using namespace std;
// Function return count of such // substring int countOfSubstrings(string s)
{ int n = s.length();
// Selection of adequate x value
int x = sqrt (n);
// Store where 1's are located
vector< int > ones;
for ( int i = 0; i < n; i++) {
if (s[i] == '1' )
ones.push_back(i);
}
// If there are no ones,
// then answer is 0
if (ones.size() == 0)
return 0;
// For ease of implementation
ones.push_back(n);
// Count storage
vector< int > totCount(n * x + n);
int sum = 0;
// Iterate on all k values less
// than fixed x
for ( int k = 0; k <= x; k++) {
// Keeps a count of 1's occurred
// during string traversal
int now = 0;
totCount[k * n]++;
// Iterate on string and modify
// the totCount
for ( int j = 1; j <= n; j++) {
// If this character is 1
if (s[j - 1] == '1' )
now++;
int index = j - k * now;
// Add to the final sum/count
sum += totCount[index + k * n];
// Increase totCount at exterior
// position
totCount[index + k * n]++;
}
now = 0;
totCount[k * n]--;
for ( int j = 1; j <= n; j++) {
if (s[j - 1] == '1' )
now++;
int index = j - k * now;
// Reduce totCount at index + k*n
totCount[index + k * n]--;
}
}
// Slightly modified prefix sum storage
int prefix_sum[n];
memset (prefix_sum, -1, sizeof (prefix_sum));
// Number of 1's till i-1
int cnt = 0;
for ( int i = 0; i < n; i++) {
prefix_sum[i] = cnt;
if (s[i] == '1' )
cnt++;
}
// Traversing over string considering
// each position and finding bounds
// and count using the inequalities
for ( int k = 0; k < n; k++)
{
for ( int j = 1; j <= (n / x)
&& prefix_sum[k] + j <= cnt; j++)
{
// Calculating bounds for l and r
int l = ones[prefix_sum[k] + j - 1]
- k + 1;
int r = ones[prefix_sum[k] + j] - k;
l = max(l, j * (x + 1));
// If valid then add to answer
if (l <= r) {
sum += r / j - (l - 1) / j;
}
}
}
return sum;
} int main()
{ string S = "1111100000" ;
cout << countOfSubstrings(S);
return 0;
} |
// Java program to count number of // subString under given condition import java.util.*;
class GFG{
// Function return count of such // substring static int countOfSubStrings(String s)
{ int n = s.length();
// Selection of adequate x value
int x = ( int )Math.sqrt(n);
// Store where 1's are located
Vector<Integer> ones = new Vector<Integer>();
for ( int i = 0 ; i < n; i++)
{
if (s.charAt(i) == '1' )
ones.add(i);
}
// If there are no ones,
// then answer is 0
if (ones.size() == 0 )
return 0 ;
// For ease of implementation
ones.add(n);
// Count storage
int []totCount = new int [n * x + n];
int sum = 0 ;
// Iterate on all k values less
// than fixed x
for ( int k = 0 ; k <= x; k++)
{
// Keeps a count of 1's occurred
// during String traversal
int now = 0 ;
totCount[k * n]++;
// Iterate on String and modify
// the totCount
for ( int j = 1 ; j <= n; j++)
{
// If this character is 1
if (s.charAt(j - 1 ) == '1' )
now++;
int index = j - k * now;
// Add to the final sum/count
sum += totCount[index + k * n];
// Increase totCount at exterior
// position
totCount[index + k * n]++;
}
now = 0 ;
totCount[k * n]--;
for ( int j = 1 ; j <= n; j++)
{
if (s.charAt(j - 1 ) == '1' )
now++;
int index = j - k * now;
// Reduce totCount at index + k*n
totCount[index + k * n]--;
}
}
// Slightly modified prefix sum storage
int []prefix_sum = new int [n];
Arrays.fill(prefix_sum, - 1 );
// Number of 1's till i-1
int cnt = 0 ;
for ( int i = 0 ; i < n; i++)
{
prefix_sum[i] = cnt;
if (s.charAt(i) == '1' )
cnt++;
}
// Traversing over String considering
// each position and finding bounds
// and count using the inequalities
for ( int k = 0 ; k < n; k++)
{
for ( int j = 1 ; j <= (n / x) &&
prefix_sum[k] + j <= cnt; j++)
{
// Calculating bounds for l and r
int l = ones.get(prefix_sum[k] + j - 1 )-
k + 1 ;
int r = ones.get(prefix_sum[k] + j) - k;
l = Math.max(l, j * (x + 1 ));
// If valid then add to answer
if (l <= r)
{
sum += r / j - (l - 1 ) / j;
}
}
}
return sum;
} // Driver code public static void main(String[] args)
{ String S = "1111100000" ;
System.out.print(countOfSubStrings(S));
} } // This code is contributed by Amit Katiyar |
# Python3 program to count number of # substring under given condition import math
# Function return count of such # substring def countOfSubstrings(s):
n = len (s)
# Selection of adequate x value
x = int (math.sqrt(n))
# Store where 1's are located
ones = []
for i in range (n):
if (s[i] = = '1' ):
ones.append(i)
# If there are no ones,
# then answer is 0
if ( len (ones) = = 0 ):
return 0
# For ease of implementation
ones.append(n)
# Count storage
totCount = [ 0 ] * (n * x + n)
sum = 0
# Iterate on all k values less
# than fixed x
for k in range (x + 1 ):
# Keeps a count of 1's occurred
# during string traversal
now = 0
totCount[k * n] + = 1
# Iterate on string and modify
# the totCount
for j in range ( 1 , n + 1 ):
# If this character is 1
if (s[j - 1 ] = = '1' ):
now + = 1
index = j - k * now
# Add to the final sum/count
sum + = totCount[index + k * n]
# Increase totCount at exterior
# position
totCount[index + k * n] + = 1
now = 0
totCount[k * n] - = 1
for j in range ( 1 , n + 1 ):
if (s[j - 1 ] = = '1' ):
now + = 1
index = j - k * now
# Reduce totCount at index + k*n
totCount[index + k * n] - = 1
# Slightly modified prefix sum storage
prefix_sum = [ - 1 ] * n
# Number of 1's till i-1
cnt = 0
for i in range (n):
prefix_sum[i] = cnt
if (s[i] = = '1' ):
cnt + = 1
# Traversing over string considering
# each position and finding bounds
# and count using the inequalities
for k in range (n):
j = 1
while (j < = (n / / x) and
prefix_sum[k] + j < = cnt):
# Calculating bounds for l and r
l = (ones[prefix_sum[k] + j - 1 ] -
k + 1 )
r = ones[prefix_sum[k] + j] - k
l = max (l, j * (x + 1 ))
# If valid then add to answer
if (l < = r):
sum + = r / / j - (l - 1 ) / / j
j + = 1
return sum
# Driver code if __name__ = = "__main__" :
S = "1111100000"
print (countOfSubstrings(S))
# This code is contributed by chitranayal |
// C# program to count number of // subString under given condition using System;
using System.Collections.Generic;
class GFG{
// Function return count of such // substring static int countOfSubStrings(String s)
{ int n = s.Length;
// Selection of adequate x value
int x = ( int )Math.Sqrt(n);
// Store where 1's are located
List< int > ones = new List< int >();
for ( int i = 0; i < n; i++)
{
if (s[i] == '1' )
ones.Add(i);
}
// If there are no ones,
// then answer is 0
if (ones.Count == 0)
return 0;
// For ease of implementation
ones.Add(n);
// Count storage
int []totCount = new int [n * x + n];
int sum = 0;
// Iterate on all k values less
// than fixed x
for ( int k = 0; k <= x; k++)
{
// Keeps a count of 1's occurred
// during String traversal
int now = 0;
totCount[k * n]++;
// Iterate on String and modify
// the totCount
for ( int j = 1; j <= n; j++)
{
// If this character is 1
if (s[j-1] == '1' )
now++;
int index = j - k * now;
// Add to the readonly sum/count
sum += totCount[index + k * n];
// Increase totCount at exterior
// position
totCount[index + k * n]++;
}
now = 0;
totCount[k * n]--;
for ( int j = 1; j <= n; j++)
{
if (s[j-1] == '1' )
now++;
int index = j - k * now;
// Reduce totCount at index + k*n
totCount[index + k * n]--;
}
}
// Slightly modified prefix sum storage
int []prefix_sum = new int [n];
for ( int i = 0; i < n; i++)
prefix_sum [i]= -1;
// Number of 1's till i-1
int cnt = 0;
for ( int i = 0; i < n; i++)
{
prefix_sum[i] = cnt;
if (s[i] == '1' )
cnt++;
}
// Traversing over String considering
// each position and finding bounds
// and count using the inequalities
for ( int k = 0; k < n; k++)
{
for ( int j = 1; j <= (n / x) &&
prefix_sum[k] + j <= cnt; j++)
{
// Calculating bounds for l and r
int l = ones[prefix_sum[k] + j - 1]-
k + 1;
int r = ones[prefix_sum[k] + j] - k;
l = Math.Max(l, j * (x + 1));
// If valid then add to answer
if (l <= r)
{
sum += r / j - (l - 1) / j;
}
}
}
return sum;
} // Driver code public static void Main(String[] args)
{ String S = "1111100000" ;
Console.Write(countOfSubStrings(S));
} } // This code is contributed by Amit Katiyar |
<script> // Javascript program to count number of // substring under given condition // Function return count of such // substring function countOfSubstrings(s)
{ var n = s.length;
// Selection of adequate x value
var x = parseInt(Math.sqrt(n));
// Store where 1's are located
var ones = [];
for ( var i = 0; i < n; i++) {
if (s[i] == '1 ')
ones.push(i);
}
// If there are no ones,
// then answer is 0
if (ones.length == 0)
return 0;
// For ease of implementation
ones.push(n);
// Count storage
var totCount = Array(n * x + n).fill(0);
var sum = 0;
// Iterate on all k values less
// than fixed x
for (var k = 0; k <= x; k++) {
// Keeps a count of 1' s occurred
// during string traversal
var now = 0;
totCount[k * n]++;
// Iterate on string and modify
// the totCount
for ( var j = 1; j <= n; j++) {
// If this character is 1
if (s[j - 1] == '1' )
now++;
var index = j - k * now;
// Add to the final sum/count
sum += totCount[index + k * n];
// Increase totCount at exterior
// position
totCount[index + k * n]++;
}
now = 0;
totCount[k * n]--;
for ( var j = 1; j <= n; j++) {
if (s[j - 1] == '1' )
now++;
var index = j - k * now;
// Reduce totCount at index + k*n
totCount[index + k * n]--;
}
}
// Slightly modified prefix sum storage
var prefix_sum = Array(n).fill(-1);
// Number of 1's till i-1
var cnt = 0;
for ( var i = 0; i < n; i++) {
prefix_sum[i] = cnt;
if (s[i] == '1')
cnt++;
}
// Traversing over string considering
// each position and finding bounds
// and count using the inequalities
for ( var k = 0; k < n; k++)
{
for ( var j = 1; j <= parseInt(n / x)
&& prefix_sum[k] + j <= cnt; j++)
{
// Calculating bounds for l and r
var l = ones[prefix_sum[k] + j - 1]
- k + 1;
var r = ones[prefix_sum[k] + j] - k;
l = Math.max(l, j * (x + 1));
// If valid then add to answer
if (l <= r) {
sum += parseInt(r / j) - parseInt((l - 1) / j);
}
}
}
return sum;
} var S = "1111100000" ;
document.write( countOfSubstrings(S)); </script> |
Output:
25
Time Complexity :
Auxiliary Space: O(N3/2)