Open In App

Number of substrings divisible by 6 in a string of integers

Given a string consisting of integers 0 to 9. The task is to count the number of substrings which when convert into integer are divisible by 6. Substring does not contain leading zeroes. Examples:

Input : s = "606".
Output : 5
Substrings "6", "0", "6", "60", "606"
are divisible by 6.

Input : s = "4806".
Output : 5
"0", "6", "48", "480", "4806" are 
substring which are divisible by 6.

Method 1: (Brute Force) The idea is to find all the substrings of the given string and check if substring is divisible by 6 or not

Time Complexity: O(n2).

 Method 2:(Dynamic Programming) As discussed in Check if a large number is divisible by 6 or not. A number is divisible by 6 if last digit is divisible by 2 and sum of digits is divisible by 3. The idea is to use Dynamic Programming, which enables us to compute answer quickly and efficiently by tracking previously computed answers and using these stored answer instead of recomputing values. 

Let f(i, m) be the number of strings starting at index i and sum of their digits modulo 3 (so far) is m and number it represents is even. So, our answer would be 

Let x be the ith digit in the string. From f(i, m) we need to find all the even substrings that start in i + 1. Also, we will get an extra substring if (x + m) itself is divisible by 3 and x is even. So, we get recurrence relation

// We initially pass m (sum modulo 3 so far) as 0
f(i, m) = ((x + m)%3 == 0 and x%2 == 0) + 
          f(i + 1, (m + x)%3)  // Recursive 

By memorizing the states, we get O(n) solution. Below is implementation of this approach: 

// C++ program to calculate number of substring
// divisible by 6.
#include <bits/stdc++.h>
#define MAX 100002
using namespace std;
  
// Return the number of substring divisible by 6
// and starting at index i in s[] and previous sum
// of digits modulo 3 is m.
int f(int i, int m, char s[], int memoize[][3])
{
    // End of the string.
    if (i == strlen(s))
        return 0;
  
    // If already calculated, return the
    // stored value.
    if (memoize[i][m] != -1)
        return memoize[i][m];
  
    // Converting into integer.
    int x = s[i] - '0';
  
    // Increment result by 1, if current digit
    // is divisible by 2 and sum of digits is
    // divisible by 3.
    // And recur for next index with new modulo.
    int ans = ((x+m)%3 == 0 && x%2 == 0) +
              f(i+1, (m+x)%3, s, memoize);
  
    return memoize[i][m] = ans;
}
  
// Returns substrings divisible by 6.
int countDivBy6(char s[])
{
    int n = strlen(s);
  
    // For storing the value of all states.
    int memoize[n+1][3];
    memset(memoize, -1, sizeof memoize);
  
    int ans = 0;
    for (int i = 0; i < strlen(s); i++)
    {
        // If string contain 0, increment count by 1.
        if (s[i] == '0')
            ans++;
  
        // Else calculate using recursive function.
        // Pass previous sum modulo 3 as 0.
        else
            ans += f(i, 0, s, memoize);
    }
  
    return ans;
}
  
// Driven Program
int main()
{
    char s[] = "4806";
  
    cout << countDivBy6(s) << endl;
  
    return 0;
}

                    
// Java program to calculate number of substring 
// divisible by 6.
import java.util.*;
  
class GFG 
{
  
    static int MAX = 100002;
  
    // Return the number of substring divisible by 6 
    // and starting at index i in s[] and previous sum 
    // of digits modulo 3 is m. 
    static int f(int i, int m, char s[], int memoize[][]) 
    {
        // End of the string. 
        if (i == s.length)
        {
            return 0;
        }
  
        // If already calculated, return the 
        // stored value. 
        if (memoize[i][m] != -1
        {
            return memoize[i][m];
        }
  
        // Converting into integer. 
        int x = s[i] - '0';
  
        // Increment result by 1, if current digit 
        // is divisible by 2 and sum of digits is 
        // divisible by 3. 
        // And recur for next index with new modulo. 
        int ans = ((x + m) % 3 == 0 && x % 2 == 0) ? 1 + f(i + 1,
                (m + x) % 3, s, memoize) : f(i + 1, (m + x) % 3, s, memoize);
        memoize[i][m] = ans;
        return memoize[i][m];
    }
  
    // Returns substrings divisible by 6. 
    static int countDivBy6(char s[]) 
    {
        int n = s.length;
  
        // For storing the value of all states. 
        int[][] memoize = new int[n + 1][3];
        for (int i = 0; i < n + 1; i++)
        {
            for (int j = 0; j < 3; j++) 
            {
                memoize[i][j] = -1;
            }
        }
  
        int ans = 0;
        for (int i = 0; i < s.length; i++) 
        {
            // If string contain 0, increment count by 1. 
            if (s[i] == '0'
            {
                ans++;
            
            // Else calculate using recursive function. 
            // Pass previous sum modulo 3 as 0. 
            else 
            {
                ans += f(i, 0, s, memoize);
            }
        }
  
        return ans;
    }
  
    // Driven Program 
    public static void main(String[] args) 
    {
        char s[] = "4806".toCharArray();
  
        System.out.println(countDivBy6(s));
    }
}
  
// This code is contributed by Rajput-Ji

                    
# Python3 program to calculate number
# of substring 
  
# Return the number of substring divisible 
# by 6 and starting at index i in s[] and 
# previous sum of digits modulo 3 is m. 
def f(i, m, s, memoize):
      
    # End of the string. 
    if (i == len(s)):
        return 0
  
    # If already calculated, return 
    # the stored value. 
    if (memoize[i][m] != -1): 
        return memoize[i][m] 
  
    # Converting into integer. 
    x = ord(s[i]) - ord('0')
  
    # Increment result by 1, if current digit 
    # is divisible by 2 and sum of digits is 
    # divisible by 3. 
    # And recur for next index with new modulo. 
    ans = (((x + m) % 3 == 0 and x % 2 == 0) +
          f(i + 1, (m + x) % 3, s, memoize)) 
  
    memoize[i][m] = ans
    return memoize[i][m]
  
# Returns substrings divisible by 6. 
def countDivBy6(s):
    n = len(s)
  
    # For storing the value of all states.
    memoize = [[-1] * 3 for i in range(n + 1)]
  
    ans = 0
    for i in range(len(s)):
          
        # If string contain 0, increment 
        # count by 1. 
        if (s[i] == '0'):
            ans += 1
  
        # Else calculate using recursive function. 
        # Pass previous sum modulo 3 as 0. 
        else:
            ans += f(i, 0, s, memoize)
  
    return ans
  
# Driver Code
if __name__ == '__main__':
    s = "4806"
  
    print(countDivBy6(s))
  
# This code is contributed by PranchalK

                    
// C# program to calculate number of substring 
// divisible by 6.
using System;
  
class GFG
{
  
    static int MAX = 100002;
  
    // Return the number of substring divisible by 6 
    // and starting at index i in s[] and previous sum 
    // of digits modulo 3 is m. 
    static int f(int i, int m, char []s, int [,]memoize) 
    {
        // End of the string. 
        if (i == s.Length)
        {
            return 0;
        }
  
        // If already calculated, return the 
        // stored value. 
        if (memoize[i,m] != -1) 
        {
            return memoize[i,m];
        }
  
        // Converting into integer. 
        int x = s[i] - '0';
  
        // Increment result by 1, if current digit 
        // is divisible by 2 and sum of digits is 
        // divisible by 3. 
        // And recur for next index with new modulo. 
        int ans = ((((x + m) % 3 == 0) && (x % 2 == 0)) ? 1 : 0)
                + f(i + 1, (m + x) % 3, s, memoize);
  
        return memoize[i,m] = ans;
    }
  
    // Returns substrings divisible by 6. 
    static int countDivBy6(char []s) 
    {
        int n = s.Length;
  
        // For storing the value of all states. 
        int[,] memoize = new int[n + 1,3];
        for (int i = 0; i < n + 1; i++)
        {
            for (int j = 0; j < 3; j++)
            {
                memoize[i,j] = -1;
            }
        }
  
        int ans = 0;
        for (int i = 0; i < s.Length; i++)
        {
            // If string contain 0, increment count by 1. 
            if (s[i] == '0'
            {
                ans++;
            
            // Else calculate using recursive function. 
            // Pass previous sum modulo 3 as 0. 
            else
            {
                ans += f(i, 0, s, memoize);
            }
        }
  
        return ans;
    }
  
    // Driver code 
    public static void Main(String[] args) 
    {
        char []s = "4806".ToCharArray();
  
        Console.WriteLine(countDivBy6(s));
    }
}
  
/* This code is contributed by PrinciRaj1992 */

                    
<script>
  
// JavaScript program to calculate number
// of substring
  
// Return the number of substring divisible
// by 6 and starting at index i in s[] and
// previous sum of digits modulo 3 is m.
function f(i, m, s, memoize){
      
    // End of the string.
    if (i == s.length)
        return 0
  
    // If already calculated, return
    // the stored value.
    if (memoize[i][m] != -1)
        return memoize[i][m]
  
    // Converting into integer.
    let x = s.charCodeAt(i) - '0'.charCodeAt(0)
  
    // Increment result by 1, if current digit
    // is divisible by 2 and sum of digits is
    // divisible by 3.
    // And recur for next index with new modulo.
    ans = (((x + m) % 3 == 0 && x % 2 == 0) + f(i + 1, (m + x) % 3, s, memoize))
  
    memoize[i][m] = ans
    return memoize[i][m]
}
  
// Returns substrings divisible by 6.
function countDivBy6(s){
    let n = s.length
  
    // For storing the value of all states.
    let memoize = new Array(n + 1)
    for(let i=0;i<n + 1;i++){
        memoize[i] = new Array(3).fill(-1)
    }
  
    let ans = 0
    for(let i=0;i<s.length;i++){
          
        // If string contain 0, increment
        // count by 1.
        if (s[i] == '0')
            ans += 1
  
        // Else calculate using recursive function.
        // Pass previous sum modulo 3 as 0.
        else
            ans += f(i, 0, s, memoize)
    }
  
    return ans
}
  
// Driver Code
  
let    s = "4806"
document.write(countDivBy6(s))
  
// This code is contributed by shinjanpatra
  
</script>

                    

Output
5

Time Complexity: O(n). 
Auxiliary Space: O(n) 


Article Tags :