Count substrings having frequency of a character exceeding that of another character in a string
Last Updated :
29 Jan, 2022
Given a string S of size N consisting of characters a, b, and c only, the task is to find the number of substrings of the given string S such that the frequency of character a is greater than the frequency of character c.
Examples:
Input: S = “abcc”
Output: 2
Explanation:
Below are all the possible substrings of S(= “abcc”) having the frequency of the character greater than the character c:
- “a”: The frequency of a and c is 1 and 0 respectively.
- “ab”: The frequency of a and c is 1 and 0 respectively.
Therefore, the count of such substrings is 2.
Input: S = “abcabcabcaaaaabbbccccc”
Output: 148
Naive Approach: The simplest approach to solve the given problem is to generate all possible substrings of the given string S and count those substrings having a count of character ‘a’ greater than the count of character ‘c’. After checking for all the substrings, print the value of the total count as the result.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
void countSubstrings(string& s)
{
int n = s.length();
int ans = 0;
for ( int i = 0; i < n; i++) {
int cnt = 0;
for ( int j = i; j < n; j++) {
if (s[j] == 'a' )
cnt++;
else if (s[j] == 'c' )
cnt--;
if (cnt > 0) {
ans++;
}
}
}
cout << ans;
}
int main()
{
string S = "abccaab" ;
countSubstrings(S);
return 0;
}
|
Java
public class GFG
{
public static void countSubstrings(String s)
{
int n = s.length();
int ans = 0 ;
for ( int i = 0 ; i < n; i++) {
int cnt = 0 ;
for ( int j = i; j < n; j++) {
if (s.charAt(j) == 'a' )
cnt++;
else if (s.charAt(j) == 'c' )
cnt--;
if (cnt > 0 ) {
ans++;
}
}
}
System.out.println(ans);
}
public static void main(String args[])
{
String S = "abccaab" ;
countSubstrings(S);
}
}
|
Python3
def countSubstrings(s):
n = len (s)
ans = 0
for i in range (n):
cnt = 0
for j in range (i, n):
if (s[j] = = 'a' ):
cnt + = 1
elif (s[j] = = 'c' ):
cnt - = 1
if (cnt > 0 ):
ans + = 1
print (ans)
if __name__ = = '__main__' :
S = "abccaab"
countSubstrings(S)
|
Javascript
<script>
function countSubstrings(s)
{
var n = s.length;
var ans = 0;
var i,j;
for (i = 0; i < n; i++) {
var cnt = 0;
for (j = i; j < n; j++) {
if (s[j] == 'a' )
cnt++;
else if (s[j] == 'c' )
cnt--;
if (cnt > 0) {
ans++;
}
}
}
document.write(ans);
}
var S = "abccaab" ;
countSubstrings(S);
</script>
|
C#
using System;
public class GFG {
public static void countSubstrings( string s)
{
int n = s.Length;
int ans = 0;
for ( int i = 0; i < n; i++) {
int cnt = 0;
for ( int j = i; j < n; j++) {
if (s[j] == 'a' )
cnt++;
else if (s[j] == 'c' )
cnt--;
if (cnt > 0) {
ans++;
}
}
}
Console.WriteLine(ans);
}
public static void Main( string [] args)
{
string S = "abccaab" ;
countSubstrings(S);
}
}
|
Time Complexity: O(N2)
Auxiliary Space: O(1)
Efficient Approach: The above approach can also be optimized by using the Segment Tree. The idea is to store the difference of frequency of characters ‘a’ and ‘c’ for all prefixes of the string S in the segment tree node. Follow the steps below to solve the problem:
- Initialize a variable, say count to 0, to store the difference between the frequency of characters ‘a’ and ‘c’.
- Initialize a variable, say ans to 0, to store the count of substrings that have the frequency of character ‘a’ greater than ‘c’.
- Initialize the segment tree with all 0s, which will be updated while traversing the string.
- Since the difference between the frequency of characters ‘a’ and ‘c’ can be negative as well, all update operations on the segment tree will be done after adding N to the index that is to be updated to avoid negative indices.
- Update the value of the index (0 + N) in the segment tree as the initial value of the count is 0.
- Traverse the given string, S over the range [0, N – 1] and perform the following steps:
- If the current character is ‘a’, then increment the count by 1. Otherwise, if the current character is ‘c’, then decrement the count by 1.
- Perform the query on the segment tree to find the sum of all values less than count, as all these substrings will have the frequency of ‘a’ greater than ‘c’ and store the value returned in a variable say val.
- Add the value of val to the variable ans.
- Update the segment tree by incrementing the value at the index (count + N) by 1.
- After completing the above steps, print the value of ans as the resultant count of substrings.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
void update( int ind, vector< int >& segTree,
int n)
{
ind += n;
segTree[ind]++;
for (; ind > 1; ind >>= 1) {
segTree[ind >> 1] = segTree[ind]
+ segTree[ind ^ 1];
}
}
int query( int low, int high,
vector< int >& segTree, int n)
{
low += n;
high += n;
int ans = 0;
while (low < high) {
if (low % 2) {
ans += segTree[low];
low++;
}
if (high % 2) {
high--;
ans += segTree[high];
}
low >>= 1;
high >>= 1;
}
return ans;
}
void countSubstrings(string& s)
{
int n = s.length();
vector< int > segTree(4 * n);
int count = 0;
update(n, segTree, 2 * n);
int ans = 0;
for ( int i = 0; i < n; i++) {
if (s[i] == 'a' )
count++;
else if (s[i] == 'c' )
count--;
int val = query(0, n + count,
segTree, 2 * n);
ans += val;
update(n + count, segTree, 2 * n);
}
cout << ans;
}
int main()
{
string S = "abccaab" ;
countSubstrings(S);
return 0;
}
|
Java
import java.util.*;
public class Main
{
static String s = "abccaab" ;
static int n = s.length();
static int [] segTree = new int [ 4 *n];
static void update( int ind, int n)
{
ind += n;
segTree[ind]++;
for (; ind > 1 ; ind >>= 1 ) {
segTree[ind >> 1 ] = segTree[ind]
+ segTree[ind ^ 1 ];
}
}
static int query( int low, int high, int n)
{
low += n;
high += n;
int ans = 0 ;
while (low < high) {
if (low % 2 != 0 ) {
ans += segTree[low];
low++;
}
if (high % 2 != 0 ) {
high--;
ans += segTree[high];
}
low >>= 1 ;
high >>= 1 ;
}
return ans;
}
static void countSubstrings()
{
int count = 0 ;
update(n, 2 * n);
int ans = 0 ;
for ( int i = 0 ; i < n; i++) {
if (s.charAt(i) == 'a' )
count++;
else if (s.charAt(i) == 'c' )
count--;
int val = query( 0 , n + count, 2 * n);
ans += val;
update(n + count, 2 * n);
}
System.out.print(ans);
}
public static void main(String[] args) {
Arrays.fill(segTree, 0 );
countSubstrings();
}
}
|
Python3
s = "abccaab"
n = len (s)
segTree = [ 0 ] * ( 4 * n)
def update(ind, n):
ind + = n
segTree[ind] + = 1
while ind > 1 :
segTree[ind >> 1 ] = segTree[ind] + segTree[ind ^ 1 ]
ind >> = 1
def query(low, high, n):
low + = n
high + = n
ans = 0
while (low < high):
if (low % 2 ! = 0 ):
ans + = segTree[low]
low + = 1
if (high % 2 ! = 0 ):
high - = 1
ans + = segTree[high]
low >> = 1
high >> = 1
return ans
def countSubstrings():
count = 0
update(n, 2 * n)
ans = 0
for i in range (n):
if (s[i] = = 'a' ):
count + = 1
elif (s[i] = = 'c' ):
count - = 1
val = query( 0 , n + count, 2 * n)
ans + = val
update(n + count, 2 * n)
print (ans)
countSubstrings()
|
C#
using System;
class GFG {
static string s = "abccaab" ;
static int n = s.Length;
static int [] segTree = new int [4*n];
static void update( int ind, int n)
{
ind += n;
segTree[ind]++;
for (; ind > 1; ind >>= 1) {
segTree[ind >> 1] = segTree[ind]
+ segTree[ind ^ 1];
}
}
static int query( int low, int high, int n)
{
low += n;
high += n;
int ans = 0;
while (low < high) {
if (low % 2 != 0) {
ans += segTree[low];
low++;
}
if (high % 2 != 0) {
high--;
ans += segTree[high];
}
low >>= 1;
high >>= 1;
}
return ans;
}
static void countSubstrings()
{
int count = 0;
update(n, 2 * n);
int ans = 0;
for ( int i = 0; i < n; i++) {
if (s[i] == 'a' )
count++;
else if (s[i] == 'c' )
count--;
int val = query(0, n + count, 2 * n);
ans += val;
update(n + count, 2 * n);
}
Console.Write(ans);
}
static void Main() {
Array.Fill(segTree, 0);
countSubstrings();
}
}
|
Javascript
<script>
s = "abccaab" ;
n = s.length
segTree = new Array(4*n);
segTree.fill(0);
function update(ind, n)
{
ind += n;
segTree[ind]++;
for (; ind > 1; ind >>= 1) {
segTree[ind >> 1] = segTree[ind]
+ segTree[ind ^ 1];
}
}
function query(low, high, n)
{
low += n;
high += n;
let ans = 0;
while (low < high) {
if (low % 2) {
ans += segTree[low];
low++;
}
if (high % 2) {
high--;
ans += segTree[high];
}
low >>= 1;
high >>= 1;
}
return ans;
}
function countSubstrings()
{
let count = 0;
update(n, 2 * n);
let ans = 0;
for (let i = 0; i < n; i++) {
if (s[i] == 'a' )
count++;
else if (s[i] == 'c' )
count--;
let val = query(0, n + count, 2 * n);
ans += val;
update(n + count, 2 * n);
}
document.write(ans);
}
countSubstrings();
</script>
|
Time Complexity: O(N*log N)
Auxiliary Space: O(N)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...