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:
- Create an array arr[] of length equals to the length of the string.
- Traverse the given string and for each corresponding index i in the string, assign arr[i] the value of current character – ‘a’.
- Find the prefix sum of the array arr[]. This prefix sum array will given sum of occurrence of all characters till each index i.
- 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> |
9 6
Time Complexity: O(N), where N is the length of the given string.
Auxiliary Space: O(N)
Please Login to comment...