阿里巴巴的手机代理商正在研究 infra 输入法的新功能。他们需要分析单词频率以改进用户输入法的体验。于是需要你在系统内核里面写一个 API。 API 有如下功能:
添加操作
添加操作格式为
insert barty 8
,意思为插入barty
这个单词,这个单词词频为 88 次。注意如果再次添加insert barty 8
操作时,就会将词频增加为 1616 次。(不会出现词频 ≤0≤0 的情况)。删除操作
删除操作格式为
delete barty
,意思为删除所有barty
这个单词。如果当前没有删除的词汇,输出
"Empty"
。查询操作
查询操作格式为
query ty
,意思为查询当前版本以ty
结尾的单词词频总和。修改操作
修改操作格式为
update ty tied
,意思为将所有结尾是ty
的单词更新为tied
结尾,比如barty
会变为bartied
。如果不存在ty
结尾的单词,输出Empty
。如果已经存在tied
结尾的单词,那么说明存在 conflict。 不做合并,输出Conflict
。如果既不存在ty
结尾的单词,也已经存在以tied
结尾的单词,则输出Empty
。
输入格式
第一行读入一个整数 TT,代表数据组数。
每组数据的第一行读入一个整数 NN 代表操作数。
接下来 NN 行,每行形容一个操作。
保证数据满足 1≤T≤101≤T≤10,1≤N≤1051≤N≤105,insert
和update
操作的字符串总长度之和 ≤106≤106,所有字符串长度 ≤106≤106,输入只有小写字母。
输出格式
输出题目中要求的结果。
样例输入
1 10 update y ty insert barty 8 delete shawn update ty tied query tied insert party 9 update y tied query ty delete barty query tied
样例输出
Empty Empty 8 Conflict 9
Empty 8
题目来源
思路:逆序字典树,转移的时候把所有节点都移过去的ok了,这样每个操作效率是O(n*26),n<1e6是没毛病的,比赛的时候想到了但是码量太大而且题目读错了造成心态爆炸,哎,果然还是太菜。
代码
:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
typedef long long LL;
struct trie
{
LL count;
trie *next[26];
};
trie *root;
trie* newtrie()
{
trie *t;
t=(trie*)malloc(sizeof(struct trie));
memset(t,0,sizeof(struct trie));
return t;
}
char oo[100000+100];
char o2[100000+100];
void Insert(char *ch,LL num)
{
int i;
trie *t,*s;
s=root;
for(i=0;ch[i];i++)
{
if(s->next[ch[i]-'a'])
{
s=s->next[ch[i]-'a'];
s->count=s->count+num;
}
else
{
t=newtrie();
s->next[ch[i]-'a']=t;
s=t;
s->count=num;
}
}
}
LL Search(char *ch)/*搜索函数,返回0则代表字典树不存在该字符串,反之亦然 */
{
int i;
trie *s=root;
if(ch[0]==0) return 0;
for(i=0;ch[i];i++)
{
if(s->next[ch[i]-'a'])
s=s->next[ch[i]-'a'];
else
break;
}
if(ch[i]==0) return s->count;
else return 0;
}
bool Delete(char *ch)/*删除函数,将该字符串从字典树中删除(删除之前记得事先判断存不存在该字符串)*/
{
int i;
trie *s;
s=root;
if(ch[0]==0)
return false;
for(i=0;ch[i];i++)
{
// printf("%c -%lld\n",ch[i],s->count);
if(s->next[ch[i]-'a'])
s=s->next[ch[i]-'a'];
else
return false;
}
LL sum=0;
sum+=s->count;
for(i=0;i<26;i++)
if(s->next[i])
sum-=s->next[i]->count;
if(sum==0)
return false;
Insert(ch,-sum);
return true;
}
LL Update(char *ch1,char *ch2)
{
LL t1,t2;
t1=Search(ch1);
t2=Search(ch2);
if(t1==0)
return -1;//printf("%d %d\n",t1,t2);
if(t2!=0)
return 1;
//
int i;
trie *t,*s;
s=root;
for(i=0;ch1[i];i++)
s=s->next[ch1[i]-'a'];
trie *pp[26];
LL sum=s->count;
for(i=0;i<26;i++)
{
pp[i]=s->next[i];
s->next[i]=NULL;
}
Insert(ch1,-sum);
s=root;
//
for(i=0;ch2[i];i++)
{
if(s->next[ch2[i]-'a'])
{
s=s->next[ch2[i]-'a'];
s->count+=sum;
}
else
{
t=newtrie();
s->next[ch2[i]-'a']=t;
s=t;
s->count=sum;
}
}
for(int i=0;i<26;i++)
s->next[i]=pp[i];
return 0;
//
}
void swap(char *ch)
{
int len=strlen(ch);
for(int i=0;i<len/2;i++)
{
char z=ch[i];
ch[i]=ch[len-1-i];
ch[len-1-i]=z;
}
}
void clear(trie *now)
{
if(now==NULL)
return ;
for(int i=0;i<26;i++)
clear(now->next[i]);
free(now);
}
int main()
{
int T;
scanf("%d",&T);
root=newtrie();
while(T--)
{
int N;
scanf("%d",&N);
clear(root);
root=newtrie();
while(N--)
{
char ope[10];
getchar();
scanf("%s",ope);
if(ope[0]=='i')
{
LL tt;
scanf("%s %lld",oo,&tt);
swap(oo);
Insert(oo,tt);
}
if(ope[0]=='d')
{
scanf("%s",oo);
swap(oo);
bool q=Delete(oo);
if(q==false)
printf("Empty\n");
}
if(ope[0]=='q')
{
scanf("%s",oo);
swap(oo);
LL z=Search(oo);
if(z==0)
printf("0\n");
else
printf("%lld\n",z);
}
if(ope[0]=='u')
{
scanf("%s %s",oo,o2);
swap(oo);
swap(o2);
int z=Update(oo,o2);
if(z==-1)
printf("Empty\n");
if(z==1)
printf("Conflict\n");
// printf("\n\n%d\n\n",z);
}
}
}
return 0;
}