阿里巴巴的手机代理商正在研究 infra 输入法的新功能。他们需要分析单词频率以改进用户输入法的体验。于是需要你在系统内核里面写一个 API。 API 有如下功能:
添加操作
添加操作格式为
insert barty 8
,意思为插入barty
这个单词,这个单词词频为 88 次。注意如果再次添加insert barty 8
操作时,就会将词频增加为 1616 次。(不会出现词频 \le 0≤0 的情况)。删除操作
删除操作格式为
delete barty
,意思为删除所有barty
这个单词。如果当前没有删除的词汇,输出
Empty
。查询操作
查询操作格式为
query ty
,意思为查询当前版本以ty
结尾的单词词频总和。
输入格式
第一行读入一个整数 TT,代表数据组数。
每组数据的第一行读入一个整数 NN 代表操作数。
接下来 NN 行,每行形容一个操作。
保证数据满足 1 \le T \le 101≤T≤10,1 \le N \le 10001≤N≤1000,insert
操作的字符串总长度之和 \le 3000≤3000,所有字符串长度 \le 10000≤10000,输入只有小写字母。
输出格式
输出题目中要求的结果。
样例输入
1 6 insert barty 8 query ty insert party 9 query ty delete barty query ty
样例输出
8 17 9
题目来源
官方题解:
只要三个操作,带权添加,删除和查询。
我们注意到 N ≤ 1000 ,所有字符长度 ≤ 10000 ,然而插入字符长度总和 ≤ 3000 。
于是就可以用暴力:
1. 对于 insert 操作,插入单词时,枚举所有后缀插入到 unordered_map 里面。
2. 对于 delete 操作,枚举所有后缀在 unordered_map 里面减掉相应单词数量。
3. 对于查询操作 O(1) 输出即可。
维护一个 unordered_map<string , ll> 代表后缀,再维护一个 unordered_map<string ,
ll> 代表某个单词确切出现过多少次。
时间复杂度 O(N ∗ L) ,空间复杂度 O(L ∗ L) 。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
unordered_map<string,ll> Suf,Word;
int main()
{
string op,words;
int update;
int caset;//scanf("%d",&caset);
cin>>caset;
while(caset--) {
Suf.erase(Suf.begin(),Suf.end());
Word.erase(Word.begin(),Word.end());
int n;
//scanf("%d",&n);
cin>>n;
for(int i=0;i<n;i++) {
cin>>op;
if(op == "insert") {
cin>>words>>update;
Word[words] += update;
for(int i=0;i<words.length();i++) {
//cout<<words.substr(i,words.length()-i)<<endl;
Suf[words.substr(i,words.length()-i)] += update;
}
}
else if(op == "delete") {
cin>>words;
if(Word[words] == 0) cout<<"Empty"<<endl;
else
{
for(int i=0;i<words.length();i++) {
Suf[words.substr(i,words.length()-i)] -= Word[words];
}
Word[words] = 0;
}
}
else if(op == "query"){
cin>>words;
cout<<Suf[words]<<endl;
}
}
}
return 0;
}