Perform range sum queries on string as per given condition

• Last Updated : 21 May, 2021

Given a string S with lowercase alphabets only and Q queries where each query contains a pair {L, R}. For each query {L, R}, there exists a substring S[L, R], the task is to find the value of the product of the frequency of each character in substring with their position in alphabetical order.
Note: Consider 1-based indexing.
Examples:

Input: S = “abcd”, Q = { {2, 4}, {1, 3} }
Output: 9 6
Explanation:
For 1st query,
substring is S[2, 4] = “bcd”. Therefore the frequency of b, c, d are 1, 1, 1 in range 2 to 4.
value = 2*(1) + 3*(1) + 4*(1) = 9.
For 2nd query,
substring is S[1, 3] = “abc”. Therefore the frequency of a, b, c are 1, 1, 1 in range 1 to 3.
value = 1*(1) + 2*(1) + 3*(1) = 6.
Input: S = “geeksforgeeks”, Q = { {3, 3}, {2, 6}, {1, 13} }
Output: 5 46 133

Naive Approach: The naive idea is to traverse for each ranges [L, R] in the query and keep the count of each character in an array. After traversing the range find the value of the expression 1*(occurrences of ‘a’) + 2*(occurrences of ‘b’) + 3*(occurrences of ‘c’) + ..+ 26*(occurrences of ‘z’)
Time Complexity: O(N*Q), where N is the length of the given string.
Auxiliary Space: O(1)
Efficient Approach: The idea is to use the Prefix Sum of the whole string by which we can perform each query in constant time. Below are the steps:

1. Create an array arr[] of length equals to the length of the string.
2. Traverse the given string and for each corresponding index i in the string, assign arr[i] the value of current character – ‘a’.
3. Find the prefix sum of the array arr[]. This prefix sum array will given sum of occurrence of all characters till each index i.
4. Now for each query(say {L, R}) the value of arr[R – 1] – arr[L – 2] will give the value of the given expression.

Below is the implementation of the above approach:

C++

 // C++ program for the above approach#include using namespace std; // Function to perform range sum queries// on string as per the given conditionvoid Range_sum_query(string S,                     vector > Query){    // Initialize N by string size    int N = S.length();     // Create array A[] for prefix sum    int A[N];     A = S - 'a' + 1;     // Iterate till N    for (int i = 1; i < N; i++) {        A[i] = S[i] - 'a' + 1;        A[i] = A[i] + A[i - 1];    }     // Traverse the queries    for (int i = 0; i < Query.size(); i++) {         if (Query[i].first == 1) {             // Check if if L == 1 range            // sum will be A[R-1]            cout << A[(Query[i].second) - 1]                 << endl;        }         else {             // Condition if L > 1 range sum            // will be A[R-1] - A[L-2]            cout << A[(Query[i].second) - 1]                        - A[(Query[i].first) - 2]                 << endl;        }    }} // Driver Codeint main(){    // Given string    string S = "abcd";     vector > Query;     // Given Queries    Query.push_back(make_pair(2, 4));    Query.push_back(make_pair(1, 3));     // Function call    Range_sum_query(S, Query);    return 0;}

Java

 // Java program for the above approachimport java.util.*; class GFG{     static class pair{    int first, second;    public pair(int first, int second)    {        this.first = first;        this.second = second;    }} // Function to perform range sum queries// on String as per the given conditionstatic void Range_sum_query(String S,                            Vector Query){         // Initialize N by String size    int N = S.length();     // Create array A[] for prefix sum    int []A = new int[N];     A = S.charAt(0) - 'a' + 1;     // Iterate till N    for(int i = 1; i < N; i++)    {        A[i] = S.charAt(i) - 'a' + 1;        A[i] = A[i] + A[i - 1];    }     // Traverse the queries    for(int i = 0; i < Query.size(); i++)    {        if (Query.get(i).first == 1)        {                         // Check if if L == 1 range            // sum will be A[R-1]            System.out.print(                A[(Query.get(i).second) - 1] + "\n");        }         else        {                         // Condition if L > 1 range sum            // will be A[R-1] - A[L-2]            System.out.print(                A[(Query.get(i).second) - 1] -                A[(Query.get(i).first) - 2] + "\n");        }    }} // Driver Codepublic static void main(String[] args){         // Given String    String S = "abcd";     Vector Query = new Vector();     // Given Queries    Query.add(new pair(2, 4));    Query.add(new pair(1, 3));     // Function call    Range_sum_query(S, Query);}} // This code is contributed by Rajput-Ji

Python3

 # Python3 program for the above approach # Function to perform range sum queries# on string as per the given conditiondef Range_sum_query(S, Query):     # Initialize N by string size    N = len(S)     # Create array A[] for prefix sum    A =  * N     A = ord(S) - ord('a') + 1     # Iterate till N    for i in range(1, N):        A[i] = ord(S[i]) - ord('a') + 1        A[i] = A[i] + A[i - 1]     # Traverse the queries    for i in range(len(Query)):        if(Query[i] == 1):             # Check if if L == 1 range            # sum will be A[R-1]            print(A[Query[i] - 1])         else:             # Condition if L > 1 range sum            # will be A[R-1] - A[L-2]            print(A[Query[i] - 1] -                  A[Query[i] - 2]) # Driver Code # Given stringS = "abcd" Query = [] # Given QueriesQuery.append([2, 4])Query.append([1, 3]) # Function callRange_sum_query(S, Query) # This code is contributed by Shivam Singh

C#

 // C# program for the above approachusing System;using System.Collections.Generic;  class GFG{   class pair  {    public int first, second;    public pair(int first, int second)    {      this.first = first;      this.second = second;    }  }   // Function to perform range sum queries  // on String as per the given condition  static void Range_sum_query(String S, List Query)  {     // Initialize N by String size    int N = S.Length;     // Create array []A for prefix sum    int[] A = new int[N];     A = S - 'a' + 1;     // Iterate till N    for (int i = 1; i < N; i++)    {      A[i] = S[i] - 'a' + 1;      A[i] = A[i] + A[i - 1];    }     // Traverse the queries    for (int i = 0; i < Query.Count; i++)    {      if (Query[i].first == 1)      {         // Check if if L == 1 range        // sum will be A[R-1]        Console.Write(A[(Query[i].second) - 1] + "\n");      }       else      {         // Condition if L > 1 range sum        // will be A[R-1] - A[L-2]        Console.Write(A[(Query[i].second) - 1] -                      A[(Query[i].first) - 2] + "\n");      }    }  }   // Driver Code  public static void Main(String[] args)  {     // Given String    String S = "abcd";     List Query = new List();     // Given Queries    Query.Add(new pair(2, 4));    Query.Add(new pair(1, 3));     // Function call    Range_sum_query(S, Query);  }} // This code is contributed by gauravrajput1

Javascript


Output:
9
6

Time Complexity: O(N), where N is the length of the given string.
Auxiliary Space: O(N)

My Personal Notes arrow_drop_up