给定一个长度为 N 的字符串S 和 Q 查询,类型如下:
Type 1: 1 i X
Update the i-th character of the string with the given character, X.
Type 2: L R
Count number of distinct characters in the given range [L, R].
Constraint:
- 1<=N<=500000
- 1<=Q<20000
- |S|=N
- String S contains only lowercase alphabets.
例子:
Input: S = “abcdbbd” Q = 6
2 3 6
1 5 z
2 1 1
1 4 a
1 7 d
2 1 7
Output:
3
1
5
Explanation:
For the Queries:
1. L = 3, R = 6
The different characters are:c, b, d.
ans = 3.
2. String after query updated as S=”abcdzbd”.
3. L = 1, R = 1
Only one different character.
and so on process all queries.
Input: S = “aaaaa”, Q = 2
1 2 b
2 1 4
Output:
2
幼稚的方法:
查询类型1:替换第i个与给定的字符字符串的字符。
查询类型 2:将字符串从 L 遍历到 R 并计算不同字符的数量。
时间复杂度: O(N 2 )
高效方法:此方法基于频率计数算法。
这个想法是使用 HashMap 将字符串的不同字符与 Ordered_set 映射,Ordered_set 存储其所有出现的索引。使用 Ordered_set 是因为它是基于红黑树的,所以插入和删除字符将花费 O ( log N )。
- 将字符串的所有字符及其索引插入 Hash-map
- 对于类型 1 的查询,删除索引 i 处出现的字符,并在 Hash-map 中插入索引 i 处出现的字符X
- 对于类型 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