Skip to content
Related Articles

Related Articles

Number of substrings with length divisible by the number of 1’s in it
  • Difficulty Level : Expert
  • Last Updated : 24 Sep, 2020

Given a binary string S consisting of only 0’s and 1’s. Count the number of substrings of this string such that length of substring is divisible by the number of 1’s in the substring.
Examples:

Input: S = “01010” 
Output: 10
Input: S = “1111100000” 
Output: 25 

Naive Approach: 

  • Iterate through all the substring and for each substring count the number of 1’s. If length of substring if divisible by 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++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program to count number of 
// substring under given condition 
#include <bits/stdc++.h>
using namespace std;
  
// Function return count of 
// such substing
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;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program to count number of 
// subString under given condition 
  
import java.util.*;
  
class GFG{
  
// Function return count of 
// such substing
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

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 program to count number of 
# substring under given condition 
  
# Function return count of 
# such substing
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

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# program to count number of 
// subString under given condition 
using System; 
  
class GFG{ 
  
// Function return count of 
// such substing 
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 

chevron_right


Output: 

25



 

Time Complexity: O(N2)
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 number of ones and k are 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 to calculate the number of integers on some segment, which give 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++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program to count number of 
// substring under given condition 
#include <bits/stdc++.h>
using namespace std;
  
// Function return count of such 
// substing
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 occured
        // 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;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program to count number of 
// subString under given condition 
import java.util.*;
  
class GFG{
  
// Function return count of such 
// substing
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 occured
        // 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

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 program to count number of 
# substring under given condition 
import math
  
# Function return count of such 
# substing
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 occured
        # 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

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# program to count number of 
// subString under given condition 
using System;
using System.Collections.Generic;
   
class GFG{
   
// Function return count of such 
// substing
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 occured
        // 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

chevron_right


Output: 

25

Time Complexity : 

O(N\sqrt{N})

 

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.

My Personal Notes arrow_drop_up
Recommended Articles
Page :