Skip to content
Related Articles

Related Articles

Improve Article

Count substrings consisting of equal number of a, b, c and d

  • Difficulty Level : Hard
  • Last Updated : 07 Jan, 2021
Geek Week

Given a string str, the task is to count non-empty substrings with equal number of ‘a’, ‘b’, ‘c’, and ‘d’.

Examples:

Input: str = “abcdef” 
Output:
Explanation: 
Substring consisting of equal number of ‘a’, ‘b’, ‘c’, and ‘d’ are { “abcd”, “abcde”, “abcdf”, “abcdef”, “e”, “f” }. 
Therefore, the required output is 6.

Input: str = “abddcdc” 
Output: 0

Approach: The problem can be solved using Hashing. The idea is to based on the following observations:



If the frequency of the characters { ‘a’, ‘b’, ‘c’, ‘d’ } in the substring {str[0], …, str[i] } is { p, q, r, s} and in the substring {str[0], …, str[j] } is { p + x, q + x, r + x, s + x }, then the substring { str[i], …, str[j] } must contain equal number of ‘a’, ‘b’, ‘c’, and ‘d’.

Follow the steps below to solve the problem: 
 

  • Initialize a variable, say cntSub, to store the count of substrings with equal number of ‘a’, ‘b’, ‘c’, ‘d’.
  • Initialize a Map, say mp, to store the relative frequency of the characters { ‘a’, ‘b’, ‘c’, ‘d’ }. 
     

If the frequency of the characters ‘a’, ‘b’, ‘c’, and ‘d’ are { p, q, r, s }, then the relative frequency of the characters are { p – y, q – y, r – y, s – y }, where y = min({p, q, r, s}) 
 

 

Below is the implementation of the above approach:

 

C++




// C++ program to implement
// the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to count the substring with
// equal number of a, b, c and d
int countSubstrings(string str)
{
 
    // Stores relative frequency of
    // the characters {'a', 'b', 'c', 'd'}
    map<pair<pair<int, int>,
             pair<int, int> >,
        int>
        mp;
 
    // Initially, frequencies of
    // 'a', 'b', 'c' and 'd' are 0.
    mp[{ { 0, 0 }, { 0, 0 } }]++;
 
    // Stores relative
    // frequency of 'a'
    int p = 0;
 
    // Stores relative
    // frequency of 'b'
    int q = 0;
 
    // Stores relative
    // frequency of 'c'
    int r = 0;
 
    // Stores relative
    // frequency of 'd'
    int s = 0;
 
    // Stores count of substring with equal
    // number of 'a', 'b', 'c' and 'd'
    int cntSub = 0;
 
    // Iterate over the characters
    // of the string
    for (int i = 0; i < str.length(); i++) {
 
        // If current character
        // is 'a'
        if (str[i] == 'a') {
 
            // Update p
            p++;
 
            // Stores minimum
            // of { p, q, r, s}
            int Y = min(min(s, r),
                        min(p, q));
 
            // Update p
            p -= Y;
 
            // Update q
            q -= Y;
 
            // Update r
            r -= Y;
 
            // Update s
            s -= Y;
        }
 
        // If current character is b
        else if (str[i] == 'b') {
 
            // Update q
            q++;
 
            // Stores minimum
            // of { p, q, r, s}
            int Y = min(min(p, q),
                        min(r, s));
 
            // Update p
            p -= Y;
 
            // Update q
            q -= Y;
 
            // Update r
            r -= Y;
 
            // Update s
            s -= Y;
        }
        else if (str[i] == 'c') {
 
            // Update r
            r++;
 
            // Stores minimum
            // of { p, q, r, s}
            int Y = min(min(p, q),
                        min(r, s));
 
            // Update p
            p -= Y;
 
            // Update q
            q -= Y;
 
            // Update r
            r -= Y;
 
            // Update s
            s -= Y;
        }
        else if (str[i] == 'd') {
 
            // Update s
            s++;
 
            // Stores minimum
            // of { p, q, r, s}
            int Y = min(min(p, q),
                        min(r, s));
 
            // Update p
            p -= Y;
 
            // Update q
            q -= Y;
 
            // Update r
            r -= Y;
 
            // Update s
            s -= Y;
        }
 
        // Update relative frequency
        // of {p, q, r, s}
        mp[{ { p, q }, { r, s } }]++;
    }
 
    // Traverse the map
    for (auto& e : mp) {
 
        // Stores count of
        // relative frequency
        int freq = e.second;
 
        // Update cntSub
        cntSub += (freq) * (freq - 1) / 2;
    }
    return cntSub;
}
 
// Driver Code
int main()
{
 
    string str = "abcdefg";
 
    // Function Call
    cout << countSubstrings(str);
    return 0;
}

Python3




# Python3 program to implement
# the above approach
 
# Function to count the substring with
# equal number of a, b, c and d
def countSubstrings(Str) :
     
    # Stores relative frequency of
    # the characters {'a', 'b', 'c', 'd'}
    mp = {}
     
    # Initially, frequencies of
    # 'a', 'b', 'c' and 'd' are 0.
    if ((0, 0), (0, 0)) in mp :
        mp[(0, 0), (0, 0)] += 1
    else :
        mp[(0, 0), (0, 0)] = 1
         
    # Stores relative
    # frequency of 'a'
    p = 0
     
    # Stores relative
    # frequency of 'b'
    q = 0
     
    # Stores relative
    # frequency of 'c'
    r = 0
     
    # Stores relative
    # frequency of 'd'
    s = 0
     
    # Stores count of substring with equal
    # number of 'a', 'b', 'c' and 'd'
    cntSub = 0
     
    # Iterate over the characters
    # of the string
    for i in range(len(Str)) :
         
        # If current character
        # is 'a'
        if (Str[i] == 'a') :
            # Update p
            p += 1
             
            # Stores minimum
            # of { p, q, r, s}
            Y = min(min(s, r), min(p, q))
             
            # Update p
            p -= Y
             
            # Update q
            q -= Y
             
            # Update r
            r -= Y
             
            # Update s
            s -= Y
             
        # If current character is b
        elif (Str[i] == 'b') :
             
            # Update q
            q += 1
             
            # Stores minimum
            # of { p, q, r, s}
            Y = min(min(p, q), min(r, s))
             
            # Update p
            p -= Y
             
            # Update q
            q -= Y
             
            # Update r
            r -= Y
             
            # Update s
            s -= Y
             
        elif (Str[i] == 'c') :
             
            # Update r
            r += 1
             
            # Stores minimum
            # of { p, q, r, s}
            Y = min(min(p, q),min(r, s))
             
            # Update p
            p -= Y
             
            # Update q
            q -= Y
             
            # Update r
            r -= Y
             
            # Update s
            s -= Y
             
        elif (Str[i] == 'd') :
             
            # Update s
            s += 1
             
            # Stores minimum
            # of { p, q, r, s}
            Y = min(min(p, q),min(r, s))
             
            # Update p
            p -= Y
             
            # Update q
            q -= Y
             
            # Update r
            r -= Y
             
            # Update s
            s -= Y
             
        # Update relative frequency
        # of {p, q, r, s}
        if ((p, q), (r, s)) in mp :
            mp[(p, q), (r, s)] += 1
        else :
            mp[(p, q), (r, s)] = 1
             
    # Traverse the map
    for e in mp :
         
        # Stores count of
        # relative frequency
         
        freq = mp[e]
         
        # Update cntSub
        cntSub += (freq) * (freq - 1) // 2
         
    return cntSub
 
  # Driver code
Str = "abcdefg"
 
# Function Call
print(countSubstrings(Str))
 
# This code is contributed by divyeshrabadiya07

C#




// C# program to implement
// the above approach
using System;
using System.Collections.Generic; 
class GFG {
     
    // Function to count the substring with
    // equal number of a, b, c and d
    static int countSubstrings(string str)
    {
       
        // Stores relative frequency of
        // the characters {'a', 'b', 'c', 'd'}
        Dictionary<Tuple<Tuple<int, int>,
      Tuple<int, int>>, int> mp =
        new Dictionary<Tuple<Tuple<int, int>,
      Tuple<int, int>>, int>(); 
       
        // Initially, frequencies of
        // 'a', 'b', 'c' and 'd' are 0.
        if(mp.ContainsKey(new Tuple<Tuple<int, int>,
                          Tuple<int, int>>(new Tuple<int, int>(0, 0),
                                           new Tuple<int, int>(0, 0))))
        {
            mp[new Tuple<Tuple<int, int>,
               Tuple<int, int>>(new Tuple<int, int>(0, 0),
                                new Tuple<int, int>(0, 0))]++;
        }
        else{
            mp[new Tuple<Tuple<int, int>,
               Tuple<int, int>>(new Tuple<int, int>(0, 0),
                                new Tuple<int, int>(0, 0))] = 1;
        }
       
        // Stores relative
        // frequency of 'a'
        int p = 0;
       
        // Stores relative
        // frequency of 'b'
        int q = 0;
       
        // Stores relative
        // frequency of 'c'
        int r = 0;
       
        // Stores relative
        // frequency of 'd'
        int s = 0;
       
        // Stores count of substring with equal
        // number of 'a', 'b', 'c' and 'd'
        int cntSub = 0;
       
        // Iterate over the characters
        // of the string
        for (int i = 0; i < str.Length; i++) {
       
            // If current character
            // is 'a'
            if (str[i] == 'a') {
       
                // Update p
                p++;
       
                // Stores minimum
                // of { p, q, r, s}
                int Y = Math.Min(Math.Min(s, r),
                            Math.Min(p, q));
       
                // Update p
                p -= Y;
       
                // Update q
                q -= Y;
       
                // Update r
                r -= Y;
       
                // Update s
                s -= Y;
            }
       
            // If current character is b
            else if (str[i] == 'b') {
       
                // Update q
                q++;
       
                // Stores minimum
                // of { p, q, r, s}
                int Y = Math.Min(Math.Min(p, q),
                            Math.Min(r, s));
       
                // Update p
                p -= Y;
       
                // Update q
                q -= Y;
       
                // Update r
                r -= Y;
       
                // Update s
                s -= Y;
            }
            else if (str[i] == 'c') {
       
                // Update r
                r++;
       
                // Stores minimum
                // of { p, q, r, s}
                int Y = Math.Min(Math.Min(p, q),
                            Math.Min(r, s));
       
                // Update p
                p -= Y;
       
                // Update q
                q -= Y;
       
                // Update r
                r -= Y;
       
                // Update s
                s -= Y;
            }
            else if (str[i] == 'd') {
       
                // Update s
                s++;
       
                // Stores minimum
                // of { p, q, r, s}
                int Y = Math.Min(Math.Min(p, q),
                            Math.Min(r, s));
       
                // Update p
                p -= Y;
       
                // Update q
                q -= Y;
       
                // Update r
                r -= Y;
       
                // Update s
                s -= Y;
            }
       
            // Update relative frequency
            // of {p, q, r, s}
            if(mp.ContainsKey(new Tuple<Tuple<int, int>,
                              Tuple<int, int>>(new Tuple<int, int>(p, q),
                                               new Tuple<int, int>(r, s))))
            {
                mp[new Tuple<Tuple<int, int>,
                   Tuple<int, int>>(new Tuple<int, int>(p, q),
                                    new Tuple<int, int>(r, s))]++;
            }
            else{
                mp[new Tuple<Tuple<int, int>,
                   Tuple<int, int>>(new Tuple<int, int>(p, q),
                                    new Tuple<int, int>(r, s))] = 1;
            }
        }
       
        // Traverse the map
        foreach(KeyValuePair<Tuple<Tuple<int, int>,
                Tuple<int, int>>, int> e in mp)
        {
       
            // Stores count of
            // relative frequency
            int freq = e.Value;
       
            // Update cntSub
            cntSub += (freq) * (freq - 1) / 2;
        }
        return cntSub;
    }
 
  // Driver code
  static void Main()
  {
       
    string str = "abcdefg";
   
    // Function Call
    Console.WriteLine(countSubstrings(str));
  }
}
 
// This code is contributed by divyesh072019

 
 

Output: 
10

 

 

Time Complexity: O(N * Log(N)) 
Auxiliary Space: O(N)

 




My Personal Notes arrow_drop_up
Recommended Articles
Page :