📌  相关文章
📜  字符串范围查询以计算具有更新的不同字符的数量

📅  最后修改于: 2021-09-07 02:29:04             🧑  作者: Mango

给定一个长度为 N 的字符串S 和 Q 查询,类型如下:

例子:

幼稚的方法:

查询类型1:替换第i个与给定的字符字符串的字符。
查询类型 2:将字符串从 L 遍历到 R 并计算不同字符的数量。

时间复杂度: O(N 2 )

高效方法:此方法基于频率计数算法。
这个想法是使用 HashMap 将字符串的不同字符与 Ordered_set 映射,Ordered_set 存储其所有出现的索引。使用 Ordered_set 是因为它是基于红黑树的,所以插入和删除字符将花费 O ( log N )。

  1. 将字符串的所有字符及其索引插入 Hash-map
  2. 对于类型 1 的查询,删除索引 i 处出现的字符,并在 Hash-map 中插入索引 i 处出现的字符X
  3. 对于类型 2 的查询,遍历所有 26 个字符并检查其出现是否在 [L, R] 范围内,如果是则增加计数。遍历后打印计数值。

下面是上述方法的实现:

C++
#include 
using namespace std;
  
#include 
#include 
using namespace __gnu_pbds;
  
#define ordered_set                 \
    tree, \
         rb_tree_tag,               \
         tree_order_statistics_node_update>
  
// Function that returns the lower-
// bound of the element in ordered_set
int lower_bound(ordered_set set1, int x)
{
    // Finding the position of
    // the element
    int pos = set1.order_of_key(x);
  
    // If the element is not
    // present in the set
    if (pos == set1.size()) {
        return -1;
    }
  
    // Finding the element at
    // the position
    else {
        int element = *(set1.find_by_order(pos));
  
        return element;
    }
}
  
// Utility function to add the
// position of all characters
// of string into ordered set
void insert(
    unordered_map& hMap,
    string S, int N)
{
    for (int i = 0; i < N; i++) {
        hMap[S[i] - 'a'].insert(i);
    }
}
  
// Utility function for update
// the character at position P
void Query1(
    string& S,
    unordered_map& hMap,
    int pos, char c)
{
  
    // we delete the position of the
    // previous character as new
    // character is to be replaced
    // at the same position.
    pos--;
    int previous = S[pos] - 'a';
    int current = c - 'a';
    S[pos] = c;
    hMap[previous].erase(pos);
    hMap[current].insert(pos);
}
  
// Utility function to determine
// number of different characters
// in given range.
void Query2(
    unordered_map& hMap,
    int L, int R)
{
    // Iterate over all 26 alphabets
    // and check if it is in given
    // range using lower bound.
    int count = 0;
    L--;
    R--;
    for (int i = 0; i < 26; i++) {
        int temp = lower_bound(hMap[i], L);
        if (temp <= R and temp != -1)
            count++;
    }
    cout << count << endl;
}
  
// Driver code
int main()
{
    string S = "abcdbbd";
    int N = S.size();
  
    unordered_map hMap;
  
    // Insert all characters with its
    // occurrence in the hash map
    insert(hMap, S, N);
  
    // Queries for sample input
    Query2(hMap, 3, 6);
    Query1(S, hMap, 5, 'z');
    Query2(hMap, 1, 1);
    Query1(S, hMap, 4, 'a');
    Query1(S, hMap, 7, 'd');
    Query2(hMap, 1, 7);
  
    return 0;
}


输出:
3
1
5

时间复杂度: O(Q * logN) ,其中 Q 是查询次数,N 是字符串的大小。

如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live