Open In App

Lexicographically smallest anagram of given string in range [L, R] for Q queries

Last Updated : 09 Feb, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given a string S of size N and an array queries, containing Q queries in the form of L, R. The task is to find the lexicographically smallest anagram of string from L to R for each query.

Example:

Input: S = “bbaacd”
queries[]={{1, 3}, {2, 5}}
Output:
aab
aacd

Input: S=”bbdfaaacaed”
queries[]={{0, 4}, {4, 8}}
Output:
abbdf
aaaac

 

Approach: This question can be solved by precomputing the frequencies of all characters present till ith index in string S, because by doing so, it’s easier as well as time-saving to calculate the frequencies of characters between L to R, in each query. Now, to solve this question, follow the below steps:

  • Create a function preComputeFreq, which will store the frequencies of characters in string S, for every index i.
  • Create a function named smallestAnagram and run it for each query. In this function:
    • Create a string ans, which will store the lexicographically smallest anagram from L to R.
    • Find the frequencies, till index R and till index L-1, to get the frequencies between L to R.
    • Run a loop from 0 to the frequency of that character and add it to the string ans.
    • Return string ans as the answer for each query.
  • Print the answer according to the above observation.

Below is the implementation of the above approach:

C++14




// C++ program for the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to calculate the frequencies of all
// characters till each index in string
void preComputeFreq(string& S,
                    vector<vector<int> >& freq)
{
    vector<int> f(26, 0);
    for (int i = 0; i < S.size(); ++i) {
        freq[i] = f;
        freq[i][S[i] - 'a']++;
 
        f = freq[i];
    }
}
 
// Function to get the
// smallest anagram from L to R
string smallestAnagram(string& S, int L, int R,
                       vector<vector<int> >& freq)
{
    string ans;
 
    // Finding net frequencies
    // of character from L to R
    for (int i = 0; i < 26; i++) {
        int low = 0;
        if (L > 0) {
            low = freq[L - 1][i];
        }
 
        // Adding characters to string ans
        for (int j = 0; j < freq[R][i] - low; j++) {
            ans += (char)('a' + i);
        }
    }
 
    return ans;
}
 
void smallestAnagramUtil(string& S, int N,
                         vector<pair<int, int> >& queries)
{
    vector<vector<int> > freq(N, vector<int>(26, 0));
    preComputeFreq(S, freq);
 
    for (auto x : queries) {
        int L = x.first;
        int R = x.second;
        cout << smallestAnagram(S, L, R, freq)
          << endl;
    }
}
 
// Driver Code
int main()
{
    string S = "bbdfaaacaed";
    int N = S.size();
    vector<pair<int, int> > queries
        = { { 0, 4 }, { 4, 8 } };
    smallestAnagramUtil(S, N, queries);
}


Java




// Java code for the above approach
import java.util.ArrayList;
import java.util.List;
 
public class Main
{
   
  // Function to calculate the frequencies of all
  // characters till each index in string
  public static void preComputeFreq(String S, List<int[]> freq) {
    int[] f = new int[26];
    for (int i = 0; i < S.length(); ++i) {
      freq.set(i, f.clone());
      freq.get(i)[S.charAt(i) - 'a']++;
 
      f = freq.get(i);
    }
  }
 
  // Function to get the
  // smallest anagram from L to R
  public static String smallestAnagram(String S, int L, int R, List<int[]> freq) {
    String ans = "";
 
    // Finding net frequencies
    // of character from L to R
    for (int i = 0; i < 26; i++) {
      int low = 0;
      if (L > 0) {
        low = freq.get(L - 1)[i];
      }
 
      // Adding characters to string ans
      for (int j = 0; j < freq.get(R)[i] - low; j++) {
        ans += (char)('a' + i);
      }
    }
 
    return ans;
  }
 
  public static void smallestAnagramUtil(String S, int N, List<int[]> queries) {
    List<int[]> freq = new ArrayList<>();
    for (int i = 0; i < N; i++) {
      freq.add(new int[26]);
    }
    preComputeFreq(S, freq);
 
    for (int[] x : queries) {
      int L = x[0];
      int R = x[1];
      System.out.println(smallestAnagram(S, L, R, freq));
    }
  }
 
  // Driver Code
  public static void main(String[] args) {
    String S = "bbdfaaacaed";
    int N = S.length();
    List<int[]> queries = new ArrayList<>();
    queries.add(new int[] {0, 4});
    queries.add(new int[] {4, 8});
    smallestAnagramUtil(S, N, queries);
  }
}
//This code is contributed by ik_9


Python3




## Python program for the above approach:
 
## Function to calculate the frequencies of all
## characters till each index in string
def preComputeFreq(S, freq):
    for i in range(len(S)):
        freq[i] = [0]*26
        freq[i][ord(S[i]) - ord('a')]+=1
        if(i > 0):
            for j in range(26):
                freq[i][j] += freq[i-1][j]
 
         
 
## Function to get the
## smallest anagram from L to R
def smallestAnagram(S, L, R, freq):
    ans = ""
 
    ## Finding net frequencies
    ## of character from L to R
    for i in range(26):
        low = 0;
        if (L > 0):
            low = freq[L - 1][i]
             
        ## Adding character to string ans
        for j in range(0, freq[R][i]-low):
            ans += chr(ord('a') + i)
    return ans
 
def smallestAnagramUtil(S, N, queries):
    freq = [0]*N
    for i in range(N):
        freq[i] = [0]*26
 
    preComputeFreq(S, freq)
     
    for x in queries:
        L = x[0]
        R = x[1]
        print(smallestAnagram(S, L, R, freq))
 
## Driver code
if __name__=='__main__':
 
    S = "bbdfaaacaed"
    N = len(S)
    queries = [ [ 0, 4 ], [ 4, 8 ] ]
    smallestAnagramUtil(S, N, queries)


Javascript




<script>
 
    // JavaScript Program to implement
    // the above approach
 
    // Function to calculate the frequencies of all
    // characters till each index in string
    function preComputeFreq(S, freq)
    {
        let f = new Array(26).fill(0);
        for (let i = 0; i < S.length; ++i) {
            freq[i] = [...f];
            freq[i][S[i].charCodeAt(0) - 'a'.charCodeAt(0)]++;
 
            f = [...freq[i]];
        }
        return freq;
    }
 
    // Function to get the
    // smallest anagram from L to R
    function smallestAnagram(S, L, R,
        freq) {
        let ans = '';
 
        // Finding net frequencies
        // of character from L to R
        for (let i = 0; i < 26; i++) {
            let low = 0;
            if (L > 0) {
                low = freq[L - 1][i];
            }
 
            // Adding characters to string ans
            for (let j = 0; j < freq[R][i] - low; j++) {
                ans = ans + String.fromCharCode('a'.charCodeAt(0) + i);
            }
        }
 
        return ans;
    }
 
    function smallestAnagramUtil(S, N,
        queries) {
        let freq = new Array(N);
 
        for (let i = 0; i < freq.length; i++) {
            freq[i] = new Array(26).fill(0);
        }
        freq = preComputeFreq(S, freq);
 
        for (let i = 0; i < queries.length; i++) {
            let L = queries[i][0];
            let R = queries[i][1];
            document.write(smallestAnagram(S, L, R, freq) + '<br>');
        }
    }
 
    // Driver Code
    let S = "bbdfaaacaed";
    let N = S.length;
    let queries
        = [[0, 4], [4, 8]];
    smallestAnagramUtil(S, N, queries);
 
// This code is contributed by Potta Lokesh
</script>


C#




using System;
using System.Collections.Generic;
 
 
    class GFG
    {
        // Function to calculate the frequencies of all
        // characters till each index in string
        public static void PreComputeFreq(string S, List<int[]> freq) {
            int[] f = new int[26];
            for (int i = 0; i < S.Length; ++i) {
                freq[i] = (int[])f.Clone();
                freq[i][S[i] - 'a']++;
                f = freq[i];
            }
        }
 
        // Function to get the
        // smallest anagram from L to R
        public static string SmallestAnagram(string S, int L, int R, List<int[]> freq) {
            string ans = "";
 
            // Finding net frequencies
            // of character from L to R
            for (int i = 0; i < 26; i++) {
                int low = 0;
                if (L > 0) {
                    low = freq[L - 1][i];
                }
 
                // Adding characters to string ans
                for (int j = 0; j < freq[R][i] - low; j++) {
                    ans += (char)('a' + i);
                }
            }
 
            return ans;
        }
 
        public static void SmallestAnagramUtil(string S, int N, List<int[]> queries) {
            List<int[]> freq = new List<int[]>();
            for (int i = 0; i < N; i++) {
                freq.Add(new int[26]);
            }
            PreComputeFreq(S, freq);
 
            foreach (int[] x in queries) {
                int L = x[0];
                int R = x[1];
                Console.WriteLine(SmallestAnagram(S, L, R, freq));
            }
        }
 
        // Driver Code
        static void Main(string[] args) {
            string S = "bbdfaaacaed";
            int N = S.Length;
            List<int[]> queries = new List<int[]>() {
                new int[] {0, 4},
                new int[] {4, 8}
            };
            SmallestAnagramUtil(S, N, queries);
        }
    }


Output

abbdf
aaaac

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



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

Similar Reads