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