// 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