📌  相关文章
📜  查询以更新来计算子字符串的字符的ASCII值的平方和

📅  最后修改于: 2021-04-17 10:00:40             🧑  作者: Mango

给定长度为N的字符串S和由以下类型的M个查询组成的字符串Q [] []的二维数组:

  • 查询(“U”,“I”,“X”):更新在与字符X索引的字符。
  • Query(“ S”,“ L”,“ R”):根据英文字母打印子字符串{S [L],…。,S [R]}中字符位置的平方和。

例子:

天真的方法:解决问题的最简单方法是遍历每个查询和类型为“ S”的查询的数组Q [] [] ,只需遍历子字符串{S [L],…,S [R]}和打印英文字母中字符位置的平方和。在执行“ U”类型查询的每次迭代中,只需将X分配给S [I]。

时间复杂度: O(N * M)
辅助空间: O(1)

高效的方法:可以通过使用“段树”数据结构来优化上述方法。请按照以下步骤解决问题:

  • 初始化一个段树,例如tree [] ,其中每个节点在其子树中存储英文字母中字符位置的平方和。
  • 对于Query(“ U”,“ I”,“ X”) ,定义一个更新函数,类似于求和范围查询的更新函数。更新S [i] = X ,然后调用update()函数更新段树。
  • 对于Query(“ S”,“ L”,“ R”) ,定义一个函数sum () ,类似于总和范围查询,然后打印通过调用子字符串{S [L]query()函数获得的总和。 ,…。,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;
}
 
// Fucntion 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;
}
 
// Fucntion 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)
 
# Fucntion 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)