Skip to content
Related Articles
Get the best out of our app
GeeksforGeeks App
Open App
geeksforgeeks
Browser
Continue

Related Articles

Perform range sum queries on string as per given condition

Improve Article
Save Article
Like Article
Improve Article
Save Article
Like Article

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 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 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 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 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 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)


My Personal Notes arrow_drop_up
Last Updated : 30 Jun, 2022
Like Article
Save Article
Similar Reads
Related Tutorials