Perform range sum queries on string as per given condition

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 condition ` `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[N]; ` ` `  `    ``A[0] = S[0] - ``'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 Code ` `int` `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 approach ` `import` `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 condition ` `static` `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[``0``] = 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 Code ` `public` `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 condition ` `def` `Range_sum_query(S, Query): ` ` `  `    ``# Initialize N by string size ` `    ``N ``=` `len``(S) ` ` `  `    ``# Create array A[] for prefix sum ` `    ``A ``=` `[``0``] ``*` `N ` ` `  `    ``A[``0``] ``=` `ord``(S[``0``]) ``-` `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][``0``] ``=``=` `1``): ` ` `  `            ``# Check if if L == 1 range ` `            ``# sum will be A[R-1] ` `            ``print``(A[Query[i][``1``] ``-` `1``]) ` ` `  `        ``else``: ` ` `  `            ``# Condition if L > 1 range sum ` `            ``# will be A[R-1] - A[L-2] ` `            ``print``(A[Query[i][``1``] ``-` `1``] ``-` `                  ``A[Query[i][``0``] ``-` `2``]) ` ` `  `# Driver Code ` ` `  `# Given string ` `S ``=` `"abcd"` ` `  `Query ``=` `[] ` ` `  `# Given Queries ` `Query.append([``2``, ``4``]) ` `Query.append([``1``, ``3``]) ` ` `  `# Function call  ` `Range_sum_query(S, Query) ` ` `  `# This code is contributed by Shivam Singh `

C#

 `// C# program for the above approach ` `using` `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[0] = S[0] - ``'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`

Output:

```9
6
```

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

My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.