Open In App

Queries to calculate difference between the frequencies of the most and least occurring characters in specified substring

Last Updated : 16 Aug, 2021
Improve
Improve
Like Article
Like
Save
Share
Report

Given a string str consisting of N lowercase characters and an array Q[][] with each row of the form {l, r} representing a query. For each query, the task is to find the difference between the maximum frequency and minimum frequency of the characters in the substring {str[l], …. str[r]}

Note: Consider 1 – based indexing.

Examples:

Input: N = 7, S = “abaabac”, Q[][] = {{ 2, 6 }, { 1, 7 }}
Output: 1 3
Explanation:
Query 1: ‘a’ occurs maximum number of times in the given range i.e., 3 and ‘b’ occurs minimum number of times in the given range i.e. 2. Therefore, output = 3 – 2 = 1.
Query 2: ‘a’ occurs maximum number of times in the given range i.e. 4 and ‘c’ occurs minimum number of times in the given range i.e. 1. Therefore, output = 4 – 1 = 3.

Input: N = 6, S = “aabbcc”, Q[][] = {{1, 4}, {1, 6}}
Output: 0 0
Explanation:
Query 1: ‘a’ and ‘b’ both occurs same number of times in the given range. Therefore, the output is 0.
Query 2: All ‘a’, ‘b’ and ‘c’ occurs same number of times in the given range. Therefore, the output is 0.

Naive Approach: For each query, find the frequencies of all characters in the given range, and take the difference between the maximum and minimum frequencies.

Time Complexity: O((N + 26)* |Q|) 
Auxiliary Space: O(26)

Below is the implementation of the above approach:

C++




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to find difference between maximum and
// minimum frequency of a character in given range
void maxDiffFreq(vector<pair<int, int> > queries,
                 string S)
{
 
    // Stores length of string
    int N = S.size();
 
    // Stores count of queries
    int Q = queries.size();
 
    // Iterate over the characters
    // of the string
    for (int i = 0; i < Q; ++i) {
 
        // Stores l-value of a query
        int l = queries[i].first - 1;
 
        // Stores r-value of a query
        int r = queries[i].second - 1;
        int freq[26] = { 0 };
 
        // Store count of every character
        // laying in range [l, r]
        for (int j = l; j <= r; j++) {
 
            // Update frequency of
            // current character
            freq[S[j] - 'a']++;
        }
 
        // Stores maximum frequency
        // of characters in given range
        int mx = 0;
 
        // Stores minimum frequency
        // of characters in given range
        int mn = 99999999;
 
        // Iterate over all possible characters
        // of the given string
        for (int j = 0; j < 26; j++) {
 
            // Update mx
            mx = max(mx, freq[j]);
 
            // If (j + 'a') is present
            if (freq[j])
                mn = min(mn, freq[j]);
        }
 
        // difference between max and min
        cout << mx - mn << endl;
    }
}
 
// Driver Code
int main()
{
 
    // Given string
    string S = "abaabac";
 
    // Given queries
    vector<pair<int, int> > queries{ { 2, 6 }, { 1, 7 } };
 
    // Function Call
    maxDiffFreq(queries, S);
}


Java




// Java program for the above approach
import java.util.*;
class GFG{
 
  // Function to find difference between maximum and
  // minimum frequency of a character in given range
  static void maxDiffFreq(int [][]queries,
                          String S)
  {
 
    // Stores length of String
    int N = S.length();
 
    // Stores count of queries
    int Q = queries.length;
 
    // Iterate over the characters
    // of the String
    for (int i = 0; i < Q; ++i)    
    {
 
      // Stores l-value of a query
      int l = queries[i][0] - 1;
 
      // Stores r-value of a query
      int r = queries[i][1] - 1;
      int freq[] = new int[26];
 
      // Store count of every character
      // laying in range [l, r]
      for (int j = l; j <= r; j++) {
 
        // Update frequency of
        // current character
        freq[S.charAt(j) - 'a']++;
      }
 
      // Stores maximum frequency
      // of characters in given range
      int mx = 0;
 
      // Stores minimum frequency
      // of characters in given range
      int mn = 99999999;
 
      // Iterate over all possible characters
      // of the given String
      for (int j = 0; j < 26; j++) {
 
        // Update mx
        mx = Math.max(mx, freq[j]);
 
        // If (j + 'a') is present
        if (freq[j]>0)
          mn = Math.min(mn, freq[j]);
      }
 
      // difference between max and min
      System.out.print(mx - mn +"\n");
    }
  }
 
  // Driver Code
  public static void main(String[] args)
  {
 
    // Given String
    String S = "abaabac";
 
    // Given queries
    int [][]queries = { { 2, 6 }, { 1, 7 } };
 
    // Function Call
    maxDiffFreq(queries, S);
  }
}
// This code is contributed by 29AjayKumar


Python3




# Python 3 program for the above approach
 
# Function to find difference between maximum
# and minimum frequency of a character in
# given range
def maxDiffFreq(queries, S):
 
    # Stores length of string
    N = len(S)
 
    # Stores count of queries
    Q = len(queries)
 
    # Iterate over the characters
    # of the string
    for i in range(Q):
 
        # Stores l-value of a query
        l = queries[i][0] - 1
 
        # Stores r-value of a query
        r = queries[i][1] - 1
        freq = [0] * 26
 
        # Store count of every character
        # laying in range [l, r]
        for j in range(l, r + 1):
 
            # Update frequency of
            # current character
            freq[ord(S[j]) - ord('a')] += 1
 
        # Stores maximum frequency
        # of characters in given range
        mx = 0
 
        # Stores minimum frequency
        # of characters in given range
        mn = 99999999
 
        # Iterate over all possible characters
        # of the given string
        for j in range(26):
 
            # Update mx
            mx = max(mx, freq[j])
 
            # If (j + 'a') is present
            if (freq[j]):
                mn = min(mn, freq[j])
 
        # Difference between max and min
        print(mx - mn)
 
# Driver Code
if __name__ == "__main__":
 
    # Given string
    S = "abaabac"
 
    # Given queries
    queries = [ [ 2, 6 ], [ 1, 7 ] ]
 
    # Function Call
    maxDiffFreq(queries, S)
 
# This code is contributed by chitranayal


C#




// C# program for the above approach
using System;
using System.Collections.Generic;
class GFG
{
     
    // Function to find difference between maximum and
    // minimum frequency of a character in given range
    static void maxDiffFreq(List<Tuple<int, int>> queries, string S)
    {
         
        // Stores length of string
        int N = S.Length;
       
        // Stores count of queries
        int Q = queries.Count;
       
        // Iterate over the characters
        // of the string
        for (int i = 0; i < Q; ++i)
        {
       
            // Stores l-value of a query
            int l = queries[i].Item1 - 1;
       
            // Stores r-value of a query
            int r = queries[i].Item2 - 1;
            int[] freq = new int[26];
       
            // Store count of every character
            // laying in range [l, r]
            for (int j = l; j <= r; j++)
            {
       
                // Update frequency of
                // current character
                freq[S[j] - 'a']++;
            }
       
            // Stores maximum frequency
            // of characters in given range
            int mx = 0;
       
            // Stores minimum frequency
            // of characters in given range
            int mn = 99999999;
       
            // Iterate over all possible characters
            // of the given string
            for (int j = 0; j < 26; j++)
            {
       
                // Update mx
                mx = Math.Max(mx, freq[j]);
       
                // If (j + 'a') is present
                if (freq[j] != 0)
                    mn = Math.Min(mn, freq[j]);
            }
       
            // difference between max and min
            Console.WriteLine(mx - mn);
        }
    }   
 
  // Driver code
  static void Main()
  {
       
    // Given string
    string S = "abaabac";
   
    // Given queries
    List<Tuple<int, int>> queries = new List<Tuple<int, int>>();
    queries.Add(new Tuple<int, int>(2, 6));
    queries.Add(new Tuple<int, int>(1, 7));
   
    // Function Call
    maxDiffFreq(queries, S);
  }
}
 
// This code is contributed by divyeshrabadiya07


Javascript




<script>
 
// Javascript program for the above approach
 
// Function to find difference between maximum and
// minimum frequency of a character in given range
function maxDiffFreq(queries, S)
{
     
    // Stores length of string
    let N = S.length;
 
    // Stores count of queries
    let Q = queries.length;
 
    // Iterate over the characters
    // of the string
    for(let i = 0; i < Q; ++i)
    {
         
        // Stores l-value of a query
        let l = queries[i][0] - 1;
 
        // Stores r-value of a query
        let r = queries[i][1] - 1;
        let freq = new Array(26).fill(0);
 
        // Store count of every character
        // laying in range [l, r]
        for(let j = l; j <= r; j++)
        {
             
            // Update frequency of
            // current character
            freq[S[j].charCodeAt(0) -
                  'a'.charCodeAt(0)]++;
        }
 
        // Stores maximum frequency
        // of characters in given range
        let mx = 0;
 
        // Stores minimum frequency
        // of characters in given range
        let mn = 99999999;
 
        // Iterate over all possible characters
        // of the given string
        for(let j = 0; j < 26; j++)
        {
             
            // Update mx
            mx = Math.max(mx, freq[j]);
 
            // If (j + 'a') is present
            if (freq[j])
                mn = Math.min(mn, freq[j]);
        }
 
        // Difference between max and min
        document.write(mx - mn + "<br>");
    }
}
 
// Driver Code
 
// Given string
let S = "abaabac";
 
// Given queries
let queries = [ [ 2, 6 ], [ 1, 7 ] ];
 
// Function Call
maxDiffFreq(queries, S);
 
// This code contributed by _saurabh_jaiswal
 
</script>


Output: 

1
3

 

Efficient Approach: The idea is to use a 2D-Fenwick tree to store the frequency of each character. Follow the steps below to solve the problem:

  1. Create a two-dimensional Fenwick tree that stores the information about each character from ‘a’ to ‘z’.
  2. Then for each query, count the frequencies of each character in the given range using the Fenwick tree.
  3. From the frequencies found above, get the maximum and the minimum frequency.
  4. Print the difference between the maximum and minimum frequency as the answer.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to update frequency of
// a character in Fenwick tree
void update(int BIT[26][10005], int idx,
            int i, int val)
{
    while (i < 10005) {
 
        // Update frequency of (idx + 'a')
        BIT[idx][i] += val;
 
        // Update i
        i = i + (i & (-i));
    }
}
 
// Function to find the frequency of
// a character (idx + 'a') in range [1, i]
int query(int BIT[26][10005], int idx, int i)
{
 
    // Stores frequency of character, (idx + 'a')
    // in range [1, i]
    int ans = 0;
 
    while (i > 0) {
 
        // Update ans
        ans += BIT[idx][i];
 
        // Update i
        i = i - (i & (-i));
    }
    return ans;
}
 
// Function to find difference between maximum and
// minimum frequency of a character in given range
void maxDiffFreq(string s, vector<pair<int, int> > queries)
{
 
    // BIT[i][j]: Stores frequency of (i + 'a')
    // If j is a power of 2, then it stores
    // the frequency (i + 'a') of  from [1, j]
    int BIT[26][10005];
 
    // Stores length of string
    int n = s.size();
 
    // Iterate over the characters
    // of the string
    for (int i = 0; i < n; i++) {
 
        // Update the frequency of
        // s[i] in fenwick tree
        update(BIT, s[i] - 'a', i + 1, 1);
    }
 
    // Stores count of queries
    int Q = queries.size();
 
    // Iterate over all the queries
    for (int i = 0; i < Q; ++i) {
 
        // Stores maximum frequency of
        // a character in range [l, r]
        int mx = 0;
 
        // Stores minimum frequency of
        // a character in range [l, r]
 
        int mn = INT_MAX;
        int l = queries[i].first;
        int r = queries[i].second;
 
        // Iterate over all possible characters
        for (int j = 0; j < 26; j++) {
 
            // Stores frequency of (j + 'a')
            // in range [1, r]
            int p = query(BIT, j, r);
 
            // Stores frequency of (j + 'a')
            // in range [1, l - 1]
            int q = query(BIT, j, l - 1);
 
            // Update mx
            mx = max(mx, p - q);
 
            // If a character (i + 'a') present
            // in range [l, r]
            if (p > 0) {
 
                // Update mn
                mn = min(mn, p - q);
            }
        }
 
        // Print the difference between
        // max and min freq
        cout << mx - mn << endl;
    }
}
 
// Driver Code
int main()
{
 
    // Given string
    string S = "abaabac";
 
    // Given queries
    vector<pair<int, int> > queries
        = { { 2, 6 }, { 1, 7 } };
 
    // Function Call
    maxDiffFreq(S, queries);
}


Java




// Java program for the above approach
import java.util.*;
 
class GFG
{
 
// Function to update frequency of
// a character in Fenwick tree
static void update(int BIT[][], int idx,
            int i, int val)
{
    while (i < 10005)
    {
 
        // Update frequency of (idx + 'a')
        BIT[idx][i] += val;
 
        // Update i
        i = i + (i & (-i));
    }
}
 
// Function to find the frequency of
// a character (idx + 'a') in range [1, i]
static int query(int BIT[][], int idx, int i)
{
 
    // Stores frequency of character, (idx + 'a')
    // in range [1, i]
    int ans = 0;
 
    while (i > 0) {
 
        // Update ans
        ans += BIT[idx][i];
 
        // Update i
        i = i - (i & (-i));
    }
    return ans;
}
 
// Function to find difference between maximum and
// minimum frequency of a character in given range
static void maxDiffFreq(String s, int [][]queries)
{
 
    // BIT[i][j]: Stores frequency of (i + 'a')
    // If j is a power of 2, then it stores
    // the frequency (i + 'a') of  from [1, j]
    int[][] BIT = new int[26][10005];
 
    // Stores length of String
    int n = s.length();
 
    // Iterate over the characters
    // of the String
    for (int i = 0; i < n; i++) {
 
        // Update the frequency of
        // s[i] in fenwick tree
        update(BIT, s.charAt(i) - 'a', i + 1, 1);
    }
 
    // Stores count of queries
    int Q = queries.length;
 
    // Iterate over all the queries
    for (int i = 0; i < Q; ++i) {
 
        // Stores maximum frequency of
        // a character in range [l, r]
        int mx = 0;
 
        // Stores minimum frequency of
        // a character in range [l, r]
 
        int mn = Integer.MAX_VALUE;
        int l = queries[i][0];
        int r = queries[i][1];
 
        // Iterate over all possible characters
        for (int j = 0; j < 26; j++) {
 
            // Stores frequency of (j + 'a')
            // in range [1, r]
            int p = query(BIT, j, r);
 
            // Stores frequency of (j + 'a')
            // in range [1, l - 1]
            int q = query(BIT, j, l - 1);
 
            // Update mx
            mx = Math.max(mx, p - q);
 
            // If a character (i + 'a') present
            // in range [l, r]
            if (p > 0) {
 
                // Update mn
                mn = Math.min(mn, p - q);
            }
        }
 
        // Print the difference between
        // max and min freq
        System.out.print(mx - mn +"\n");
    }
}
 
// Driver Code
public static void main(String[] args)
{
 
    // Given String
    String S = "abaabac";
 
    // Given queries
    int [][]queries
        = { { 2, 6 }, { 1, 7 } };
 
    // Function Call
    maxDiffFreq(S, queries);
}
}
 
// This code is contributed by shikhasingrajput


Python3




# Python3 program for the above approach
import sys
 
# Function to update frequency of
# a character in Fenwick tree
def update(BIT, idx, i, val) :
    while (i < 10005) :
     
      # Update frequency of (idx + 'a')
      BIT[idx][i] += val
     
      # Update i
      i = i + (i & (-i))
       
# Function to find the frequency of
# a character (idx + 'a') in range [1, i]
def query(BIT, idx, i) :
 
    # Stores frequency of character, (idx + 'a')
    # in range [1, i]
    ans = 0
    while (i > 0) :
     
      # Update ans
      ans += BIT[idx][i]
     
      # Update i
      i = i - (i & (-i))
 
    return ans
     
# Function to find difference between maximum and
# minimum frequency of a character in given range
def maxDiffFreq(s, queries) :
 
    # BIT[i][j]: Stores frequency of (i + 'a')
    # If j is a power of 2, then it stores
    # the frequency (i + 'a') of  from [1][j]
    BIT = [[0 for i in range(10005)] for j in range(26)]
     
    # Stores length of String
    n = len(s)
     
    # Iterate over the characters
    # of the String
    for i in range(n) :
     
      # Update the frequency of
      # s[i] in fenwick tree
      update(BIT, ord(s[i]) - ord('a'), i + 1, 1)
     
    # Stores count of queries
    Q = len(queries)
     
    # Iterate over all the queries
    for i in range(Q) :
     
      # Stores maximum frequency of
      # a character in range [l, r]
      mx = 0
     
      # Stores minimum frequency of
      # a character in range [l, r]
      mn = sys.maxsize
      l = queries[i][0]
      r = queries[i][1]
     
      # Iterate over all possible characters
      for j in range(26) :
     
        # Stores frequency of (j + 'a')
        # in range [1, r]
        p = query(BIT, j, r)
     
        # Stores frequency of (j + 'a')
        # in range [1, l - 1]
        q = query(BIT, j, l - 1)
     
        # Update mx
        mx = max(mx, p - q)
     
        # If a character (i + 'a') present
        # in range [l, r]
        if (p > 0) :
     
          # Update mn
          mn = min(mn, p - q)
     
      # Print the difference between
      # max and min freq
      print(mx - mn)
       
# Given String
S = "abaabac"
 
# Given queries
queries = [ [ 2, 6 ], [ 1, 7 ] ]
 
# Function Call
maxDiffFreq(S, queries)
 
# This code is contributed by divyesh072019.


C#




// C# program for the above approach
using System;
public class GFG
{
 
  // Function to update frequency of
  // a character in Fenwick tree
  static void update(int [,]BIT, int idx,
                     int i, int val)
  {
    while (i < 10005)
    {
 
      // Update frequency of (idx + 'a')
      BIT[idx,i] += val;
 
      // Update i
      i = i + (i & (-i));
    }
  }
 
  // Function to find the frequency of
  // a character (idx + 'a') in range [1, i]
  static int query(int [,]BIT, int idx, int i)
  {
 
    // Stores frequency of character, (idx + 'a')
    // in range [1, i]
    int ans = 0;
    while (i > 0)
    {
 
      // Update ans
      ans += BIT[idx,i];
 
      // Update i
      i = i - (i & (-i));
    }
    return ans;
  }
 
  // Function to find difference between maximum and
  // minimum frequency of a character in given range
  static void maxDiffFreq(String s, int [,]queries)
  {
 
    // BIT[i,j]: Stores frequency of (i + 'a')
    // If j is a power of 2, then it stores
    // the frequency (i + 'a') of  from [1, j]
    int[,] BIT = new int[26, 10005];
 
    // Stores length of String
    int n = s.Length;
 
    // Iterate over the characters
    // of the String
    for (int i = 0; i < n; i++)
    {
 
      // Update the frequency of
      // s[i] in fenwick tree
      update(BIT, s[i] - 'a', i + 1, 1);
    }
 
    // Stores count of queries
    int Q = queries.GetLength(0);
 
    // Iterate over all the queries
    for (int i = 0; i < Q; ++i)
    {
 
      // Stores maximum frequency of
      // a character in range [l, r]
      int mx = 0;
 
      // Stores minimum frequency of
      // a character in range [l, r]
      int mn = int.MaxValue;
      int l = queries[i, 0];
      int r = queries[i, 1];
 
      // Iterate over all possible characters
      for (int j = 0; j < 26; j++)
      {
 
        // Stores frequency of (j + 'a')
        // in range [1, r]
        int p = query(BIT, j, r);
 
        // Stores frequency of (j + 'a')
        // in range [1, l - 1]
        int q = query(BIT, j, l - 1);
 
        // Update mx
        mx = Math.Max(mx, p - q);
 
        // If a character (i + 'a') present
        // in range [l, r]
        if (p > 0)
        {
 
          // Update mn
          mn = Math.Min(mn, p - q);
        }
      }
 
      // Print the difference between
      // max and min freq
      Console.Write(mx - mn +"\n");
    }
  }
 
  // Driver Code
  public static void Main(String[] args)
  {
 
    // Given String
    String S = "abaabac";
 
    // Given queries
    int [,]queries
      = { { 2, 6 }, { 1, 7 } };
 
    // Function Call
    maxDiffFreq(S, queries);
  }
}
 
// This code is contributed by shikhasingrajput


Javascript




<script>
 
// Javascript program for the above approach
 
// Function to update frequency of
// a character in Fenwick tree
function update(BIT, idx, i, val)
{
    while (i < 10005)
    {
         
        // Update frequency of (idx + 'a')
        BIT[idx][i] += val;
  
        // Update i
        i = i + (i & (-i));
    }
}
 
// Function to find the frequency of
// a character (idx + 'a') in range [1, i]
function query(BIT, idx, i)
{
     
    // Stores frequency of character, (idx + 'a')
    // in range [1, i]
    let ans = 0;
  
    while (i > 0)
    {
         
        // Update ans
        ans += BIT[idx][i];
  
        // Update i
        i = i - (i & (-i));
    }
    return ans;
}
 
// Function to find difference between maximum and
// minimum frequency of a character in given range
function maxDiffFreq(s, queries)
{
     
    // BIT[i][j]: Stores frequency of (i + 'a')
    // If j is a power of 2, then it stores
    // the frequency (i + 'a') of  from [1, j]
    let BIT = new Array(26);
    for(let i = 0; i < 26; i++)
    {
        BIT[i] = new Array(10005);
        for(let j = 0; j < 10005; j++)
        {
            BIT[i][j] = 0;
        }
    }
     
    // Stores length of String
    let n = s.length;
  
    // Iterate over the characters
    // of the String
    for(let i = 0; i < n; i++)
    {
         
        // Update the frequency of
        // s[i] in fenwick tree
        update(BIT, s[i].charCodeAt(0) -
                     'a'.charCodeAt(0),
                     i + 1, 1);
    }
  
    // Stores count of queries
    let Q = queries.length;
  
    // Iterate over all the queries
    for(let i = 0; i < Q; ++i)
    {
         
        // Stores maximum frequency of
        // a character in range [l, r]
        let mx = 0;
  
        // Stores minimum frequency of
        // a character in range [l, r]
        let mn = Number.MAX_VALUE;
        let l = queries[i][0];
        let r = queries[i][1];
  
        // Iterate over all possible characters
        for(let j = 0; j < 26; j++)
        {
             
            // Stores frequency of (j + 'a')
            // in range [1, r]
            let p = query(BIT, j, r);
  
            // Stores frequency of (j + 'a')
            // in range [1, l - 1]
            let q = query(BIT, j, l - 1);
  
            // Update mx
            mx = Math.max(mx, p - q);
  
            // If a character (i + 'a') present
            // in range [l, r]
            if (p > 0)
            {
                 
                // Update mn
                mn = Math.min(mn, p - q);
            }
        }
  
        // Print the difference between
        // max and min freq
        document.write(mx - mn + "<br>");
    }
}
 
// Driver Code
let S = "abaabac";
  
// Given queries
let queries = [ [ 2, 6 ], [ 1, 7 ] ];
 
// Function Call
maxDiffFreq(S, queries);
 
// This code is contributed by avanitrachhadiya2155
 
</script>


Output: 

1
3

 

Time Complexity: O(|Q| * log(N) * 26)
Auxiliary Space: O(N * 26)



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads