给定一个只有小写字母的字符串S和Q查询,其中每个查询包含一对{L, R} 。对于每个查询 {L, R} ,都存在一个子串S[L, R] ,任务是找到子串中每个字符出现的频率与其按字母顺序排列的位置的乘积的值。
注意:考虑基于 1 的索引。
例子:
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
幼稚的方法:幼稚的想法是遍历查询中的每个范围[L, R]并将每个字符的计数保留在数组中。在遍历范围后找到表达式1*(‘a’ 的出现次数) + 2*(‘b’ 的出现次数) + 3*(‘c’ 的出现次数) + ..+ 26*(‘z 的出现次数’) 。
时间复杂度: O(N*Q),其中 N 是给定字符串的长度。
辅助空间: O(1)
高效的方法:这个想法是使用整个字符串的前缀和,通过它我们可以在恒定的时间内执行每个查询。以下是步骤:
- 创建一个长度等于字符串长度的数组arr[] 。
- 横穿给定字符串和用于串中的每个对应的索引i,分配ARR当前字符的[I]的值– “A”。
- 查找数组arr[]的前缀和。这个前缀和数组将给出所有字符出现的总和,直到每个索引 i。
- 现在对于每个查询(比如{L, R} ), arr[R – 1] – arr[L – 2]的值将给出给定表达式的值。
下面是上述方法的实现:
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
Javascript
9
6
时间复杂度: O(N),其中 N 是给定字符串的长度。
辅助空间: O(N)
如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live