给定长度为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是因为它基于Red-Black树,因此字符的插入和删除将采用O(log N)。
- 将字符串的所有字符及其索引插入哈希映射
- 对于类型1的查询,请在哈希映射中删除索引i处出现的字符并在索引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现场课程》和《 Geeks现场课程美国》。