Skip to content
Related Articles

Related Articles

Improve Article
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 <bits/stdc++.h>
using namespace std;
 
// Function to perform range sum queries
// on string as per the given condition
void Range_sum_query(string S,
                     vector<pair<int, int> > 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<pair<int, int> > 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<pair> 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<pair> Query = new Vector<pair>();
 
    // 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<pair> 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<pair> Query = new List<pair>();
 
    // 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




<script>
 
// Javascript program for the above approach
 
// Function to perform range sum queries
// on string as per the given condition
function Range_sum_query(S, Query)
{
 
    // Initialize N by string size
    var N = S.length;
 
    // Create array A[] for prefix sum
    var A = Array(N);
 
    A[0] = S[0].charCodeAt(0) - 'a'.charCodeAt(0) + 1;
 
    // Iterate till N
    for (var i = 1; i < N; i++) {
        A[i] = S[i].charCodeAt(0) - 'a'.charCodeAt(0) + 1;
        A[i] = A[i] + A[i - 1];
    }
 
    // Traverse the queries
    for (var i = 0; i < Query.length; i++) {
 
        if (Query[i][0] == 1) {
 
            // Check if if L == 1 range
            // sum will be A[R-1]
            document.write( A[(Query[i][1]) - 1]+ "<br>");
        }
 
        else {
 
            // Condition if L > 1 range sum
            // will be A[R-1] - A[L-2]
            document.write( A[(Query[i][1]) - 1]
                        - A[(Query[i][0]) - 2]+ "<br>");
        }
    }
}
 
// Driver Code
// Given string
var S = "abcd";
var Query = [];
 
// Given Queries
Query.push([2, 4]);
Query.push([1, 3]);
 
// Function call
Range_sum_query(S, Query);
 
// This code is contributed by itsok.
</script>
Output: 



9
6

 

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

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with industry experts, please refer Geeks Classes Live 




My Personal Notes arrow_drop_up
Recommended Articles
Page :