给定一个长度为N的字符串S和一个由以下类型的M 个查询组成的字符串Q[][]的二维数组:
- 查询(“U”,“I”,“X”):更新在与字符X索引我的字符。
- Query(“S”, “L”, “R”):根据英文字母打印子串{S[L], …., S[R]}中字符位置的平方和。
例子:
Input: S = “geeksforgeeks”, Q[][] = {{“S”, “0”, “2”}, {“S”, “1”, “2”}, {“U”, “1”, “a”}, {“S”, “0”, “2”}, {“S”, “4”, “5”}}
Output:
99
50
75
397
Explanation:
For Query(“S”, “0”, “2”), sum of squares of the positions of the characters in the substring “gee” = 7*7 + 5*5 + 5*5 = 99.
For Query(“S”, “1”, “2”), sum of squares of the positions of the character in the substring “ee” = 5*5 + 5*5 = 50.
For Query(“U”, “1”, “a”): Replacing S[1] by ‘a’ modifies S to “gaeksforgeeks”.
For Query(“S”, “0”, “2”), sum of squares of the positions of the characters in the substring “gae” = 7*7 + 1*1 + 5*5 = 75.
For Query(“S”, “4”, “5”), sum of squares of the positions of the characters in the substring “ks” = 19*19 + 36 = 397
Input: S = “geeksforgeeks”, Q[][] = {{“S”, “1”, “2”}}
Output: 50
朴素的方法:解决问题的最简单的方法是遍历数组Q[][]为每个查询和类型‘S’ 的查询,只需遍历子字符串 {S[L], …, S[R]} 和打印英文字母中字符位置的平方和。在每次执行类型‘U’查询的迭代中,只需将X分配给S[I]。
时间复杂度: O(N * M)
辅助空间: O(1)
高效的方法:上述方法可以通过使用 Segment Tree 数据结构进行优化。请按照以下步骤解决问题:
- 初始化一个段树,比如tree[] ,其中每个节点存储其子树中英文字母中字符位置的平方和。
- 对于Query(“U”, “I”, “X”) ,定义一个更新函数,类似于求和范围查询的更新函数。更新S[i] = X然后调用update()函数来更新段树。
- 对于Query(“S”, “L”, “R”) ,定义一个函数query() ,类似于 sum range query ,然后打印通过调用query()函数获得的子串{S[L]的总和, …., S[R]} 。
下面是上述方法的实现:
C++
// C++ implementation of
// the above approach
#include
using namespace std;
// Structure of a node
// of a Segment Tree
struct treeNode {
int square_sum;
};
// Function to construct the Segment Tree
void buildTree(string s, treeNode* tree,
int start, int end,
int treeNode)
{
// If start and end are equal
if (start == end) {
// Assign squares of positions
// of the characters
tree[treeNode].square_sum
= pow(s[start] - 'a' + 1, 2);
return;
}
// Stores the mid value of
// the range [start, end]
int mid = start + ((end - start) / 2);
// Recursive call to left subtree
buildTree(s, tree, start,
mid, 2 * treeNode);
// Recursive call to right subtree
buildTree(s, tree, mid + 1,
end, 1 + 2 * treeNode);
// Update the current node
tree[treeNode].square_sum
= tree[(2 * treeNode)].square_sum
+ tree[(2 * treeNode) + 1].square_sum;
}
// Function to perform the queries of type 2
int querySquareSum(treeNode* tree, int start,
int end, int treeNode,
int l, int r)
{
// No overlap
if ((l > end) || (r < start)) {
return 0;
}
// If l <= start and r >= end
if ((l <= start) && (r >= end)) {
// Return the value of treeNode
return tree[treeNode].square_sum;
}
// Calculate middle of the range [start, end]
int mid = start + ((end - start) / 2);
// Function call to left subtree
int X = querySquareSum(tree, start,
mid, 2 * treeNode,
l, r);
// Function call to right subtree
int Y = +querySquareSum(tree, mid + 1, end,
1 + 2 * treeNode, l, r);
// Return the sum of X and Y
return X + Y;
}
// Function to perform update
// queries on a Segment Tree
void updateTree(string s, treeNode* tree,
int start, int end,
int treeNode, int idx, char X)
{
// If start is equal to end
// and idx is equal to start
if ((start == end) && (idx == start)) {
// Base Case
s[idx] = X;
tree[treeNode].square_sum
= pow(X - 'a' + 1, 2);
return;
}
// Calculate middle of the range [start, end]
int mid = start + ((end - start) / 2);
// If idx <= mid
if (idx <= mid) {
// Function call to left subtree
updateTree(s, tree, start, mid,
(2 * treeNode), idx, X);
}
// Otherwise
else {
// Function call to the right subtree
updateTree(s, tree, mid + 1, end,
(2 * treeNode) + 1, idx, X);
}
// Update the current node
tree[treeNode].square_sum
= tree[(2 * treeNode)].square_sum
+ tree[(2 * treeNode) + 1].square_sum;
}
// Function to perform the given queries
void PerformQuery(string S,
vector > Q)
{
int n = S.size();
// Stores the segment tree
treeNode* tree = new treeNode[(4 * n) + 1];
// Traverse the segment tree
for (int i = 0; i <= (4 * n); i = i + 1) {
// Assign 0 to each node
tree[i].square_sum = 0;
}
// Builds segment tree
buildTree(S, tree, 0, n - 1, 1);
// Traverse the query array Q[][]
for (int i = 0; i < Q.size(); i++) {
// If query is of type S
if (Q[i][0] == "S") {
// Stores the left boundary
int L = stoi(Q[i][1]);
// Stores the right boundary
int R = stoi(Q[i][2]);
// Prints the sum of squares of the
// alphabetic positions of the characters
cout << querySquareSum(tree, 0,
n - 1, 1, L, R)
<< endl;
}
// Otherwise
else if (Q[i][0] == "U") {
// Stores the index of the
// character to be updated
int I = stoi(Q[i][1]);
// Update the segment tree
updateTree(S, tree, 0, n - 1,
1, I, Q[i][2][0]);
}
}
}
// Driver Code
int main()
{
// Input
string S = "geeksforgeeks";
vector > Q = { { "S", "0", "2" },
{ "S", "1", "2" },
{ "U", "1", "a" },
{ "S", "0", "2" },
{ "S", "4", "5" } };
// Function call
PerformQuery(S, Q);
}
Java
// Java implementation of
// the above approach
import java.io.*;
import java.lang.*;
import java.util.*;
class GFG{
// Structure of a node
// of a Segment Tree
static class treeNode
{
int square_sum;
treeNode(int square_sum)
{
this.square_sum = square_sum;
}
};
// Function to construct the Segment Tree
static void buildTree(char s[], treeNode tree[],
int start, int end, int treenode)
{
// If start and end are equal
if (start == end)
{
// Assign squares of positions
// of the characters
tree[treenode].square_sum = (int)Math.pow(
s[start] - 'a' + 1, 2);
return;
}
// Stores the mid value of
// the range [start, end]
int mid = start + ((end - start) / 2);
// Recursive call to left subtree
buildTree(s, tree, start, mid, 2 * treenode);
// Recursive call to right subtree
buildTree(s, tree, mid + 1, end, 1 + 2 * treenode);
// Update the current node
tree[treenode].square_sum = tree[(2 * treenode)].square_sum +
tree[(2 * treenode) + 1].square_sum;
}
// Function to perform the queries of type 2
static int querySquareSum(treeNode tree[], int start,
int end, int treenode, int l,
int r)
{
// No overlap
if ((l > end) || (r < start))
{
return 0;
}
// If l <= start and r >= end
if ((l <= start) && (r >= end))
{
// Return the value of treeNode
return tree[treenode].square_sum;
}
// Calculate middle of the range [start, end]
int mid = start + ((end - start) / 2);
// Function call to left subtree
int X = querySquareSum(tree, start, mid,
2 * treenode, l, r);
// Function call to right subtree
int Y = +querySquareSum(tree, mid + 1, end,
1 + 2 * treenode, l, r);
// Return the sum of X and Y
return X + Y;
}
// Function to perform update
// queries on a Segment Tree
static void updateTree(char s[], treeNode tree[],
int start, int end, int treenode,
int idx, char X)
{
// If start is equal to end
// and idx is equal to start
if ((start == end) && (idx == start))
{
// Base Case
s[idx] = X;
tree[treenode].square_sum = (int)Math.pow(
X - 'a' + 1, 2);
return;
}
// Calculate middle of the range [start, end]
int mid = start + ((end - start) / 2);
// If idx <= mid
if (idx <= mid)
{
// Function call to left subtree
updateTree(s, tree, start, mid, (2 * treenode),
idx, X);
}
// Otherwise
else
{
// Function call to the right subtree
updateTree(s, tree, mid + 1, end,
(2 * treenode) + 1, idx, X);
}
// Update the current node
tree[treenode].square_sum = tree[(2 * treenode)].square_sum +
tree[(2 * treenode) + 1].square_sum;
}
// Function to perform the given queries
static void PerformQuery(String S, String Q[][])
{
int n = S.length();
// Stores the segment tree
treeNode tree[] = new treeNode[(4 * n) + 1];
// Traverse the segment tree
for(int i = 0; i <= (4 * n); i = i + 1)
{
// Assign 0 to each node
tree[i] = new treeNode(0);
}
char s[] = S.toCharArray();
// Builds segment tree
buildTree(s, tree, 0, n - 1, 1);
// Traverse the query array Q[][]
for(int i = 0; i < Q.length; i++)
{
// If query is of type S
if (Q[i][0] == "S")
{
// Stores the left boundary
int L = Integer.parseInt(Q[i][1]);
// Stores the right boundary
int R = Integer.parseInt(Q[i][2]);
// Prints the sum of squares of the
// alphabetic positions of the characters
System.out.println(querySquareSum(
tree, 0, n - 1, 1, L, R));
}
// Otherwise
else if (Q[i][0] == "U")
{
// Stores the index of the
// character to be updated
int I = Integer.parseInt(Q[i][1]);
// Update the segment tree
updateTree(s, tree, 0, n - 1, 1, I,
Q[i][2].charAt(0));
}
}
}
// Driver Code
public static void main(String[] args)
{
// Input
String S = "geeksforgeeks";
String Q[][] = { { "S", "0", "2" },
{ "S", "1", "2" },
{ "U", "1", "a" },
{ "S", "0", "2" },
{ "S", "4", "5" } };
// Function call
PerformQuery(S, Q);
}
}
// This code is contributed by Kingash
Python3
# Python3 implementation of
# the above approach
# Structure of a node
# of a Segment Tree
class treeNode:
def __init__(self, x):
self.square_sum = x
# Function to construct the Segment Tree
def buildTree(s, tree, start, end, treeNode):
# If start and end are equa
if (start == end):
# Assign squares of positions
# of the characters
tree[treeNode].square_sum = pow(ord(s[start]) -
ord('a') + 1, 2)
return
# Stores the mid value of
# the range [start, end]
mid = start + ((end - start) // 2)
# Recursive call to left subtree
buildTree(s, tree, start, mid, 2 * treeNode)
# Recursive call to right subtree
buildTree(s, tree, mid + 1, end,
1 + 2 * treeNode)
# Update the current node
tree[treeNode].square_sum = (tree[(2 * treeNode)].square_sum +
tree[(2 * treeNode) + 1].square_sum)
# Function to perform the queries of type 2
def querySquareSum(tree, start, end, treeNode, l, r):
# No overlap
if ((l > end) or (r < start)):
return 0
# If l <= start and r >= end
if ((l <= start) and (r >= end)):
# Return the value of treeNode
return tree[treeNode].square_sum
# Calculate middle of the range [start, end]
mid = start + ((end - start) // 2)
# Function call to left subtree
X = querySquareSum(tree, start, mid,
2 * treeNode, l, r)
# Function call to right subtree
Y = +querySquareSum(tree, mid + 1, end,
1 + 2 * treeNode, l, r)
# Return the sum of X and Y
return X + Y
# Function to perform update
# queries on a Segment Tree
def updateTree(s, tree, start, end, treeNode, idx, X):
# If start is equal to end
# and idx is equal to start
if ((start == end) and (idx == start)):
# Base Case
s[idx] = X
tree[treeNode].square_sum = pow(ord(X) -
ord('a') + 1, 2)
return
# Calculate middle of the range [start, end]
mid = start + ((end - start) // 2)
# If idx <= mid
if (idx <= mid):
# Function call to left subtree
updateTree(s, tree, start, mid,
(2 * treeNode), idx, X)
# Otherwise
else:
# Function call to the right subtree
updateTree(s, tree, mid + 1, end,
(2 * treeNode) + 1, idx, X)
# Update the current node
tree[treeNode].square_sum = (tree[(2 * treeNode)].square_sum +
tree[(2 * treeNode) + 1].square_sum)
# Function to perform the given queries
def PerformQuery(S, Q):
n = len(S)
# Stores the segment tree
tree = [treeNode(0) for i in range((4 * n) + 1)]
# Traverse the segment tree
for i in range(4 * n + 1):
# Assign 0 to each node
tree[i].square_sum = 0
# Builds segment tree
buildTree(S, tree, 0, n - 1, 1)
# Traverse the query array Q[][]
for i in range(len(Q)):
# If query is of type S
if (Q[i][0] == "S"):
# Stores the left boundary
L = int(Q[i][1])
# Stores the right boundary
R = int(Q[i][2])
# Prints the sum of squares of the
# alphabetic positions of the characters
print(querySquareSum(tree, 0, n - 1,
1, L, R))
# Otherwise
elif (Q[i][0] == "U"):
# Stores the index of the
# character to be updated
I = int(Q[i][1])
# Update the segment tree
updateTree(S, tree, 0, n - 1,
1, I, Q[i][2][0])
# Driver Code
if __name__ == '__main__':
# Input
S = "geeksforgeeks"
Q = [ [ "S", "0", "2" ],
[ "S", "1", "2" ],
[ "U", "1", "a" ],
[ "S", "0", "2" ],
[ "S", "4", "5" ] ]
# Function call
PerformQuery([i for i in S], Q)
# This code is contributed by mohit kumar 29
99
50
75
397
时间复杂度: O((N + M) * log N)
辅助空间: O(N)
如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live