Problem C
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 2902 Accepted Submission(s): 793
Problem Description
度熊手上有一本神奇的字典,你可以在它里面做如下三个操作:
1、insert : 往神奇字典中插入一个单词
2、delete: 在神奇字典中删除所有前缀等于给定字符串的单词
3、search: 查询是否在神奇字典中有一个字符串的前缀等于给定的字符串
Input
这里仅有一组测试数据。第一行输入一个正整数N(1≤N≤100000),代表度熊对于字典的操作次数,接下来N行,每行包含两个字符串,中间中用空格隔开。第一个字符串代表了相关的操作(包括: insert, delete 或者 search)。第二个字符串代表了相关操作后指定的那个字符串,第二个字符串的长度不会超过30。第二个字符串仅由小写字母组成。
Output
对于每一个search 操作,如果在度熊的字典中存在给定的字符串为前缀的单词,则输出Yes 否则输出 No。
Sample Input
5 insert hello insert hehe search h delete he search hello
Sample Output
Yes No
Source
2016"百度之星" - 资格赛(Astar Round1)
Recommend
liuyiding
分析:
插入是平常的插入,
查询的字典中前缀与该单词相同的数量,我们用一个sum记录每一个节点被增加的个数,找到输出即可
删除也是删除所有前缀等于s2的单词,也是利用sum,减去相应的前缀,最后全部清0
#include<cstdio>
#include<iostream>
#include<fstream>
#include<algorithm>
#include<functional>
#include<cstring>
#include<string>
#include<cstdlib>
#include<iomanip>
#include<numeric>
#include<cctype>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<list>
#include<set>
#include<map>
using namespace std;
#define N 300000+5
#define MAX 26
typedef long long ll;
const int maxnode=400000+100;//预计字典树最大节点数目
const int sigma_size=26; //每个节点的最多儿子数
struct Trie
{
int ch[maxnode][sigma_size];//ch[i][j]==k表示第i个节点的第j个儿子是节点k
int val[maxnode];//val[i]==x表示第i个节点的权值为x
int sum[maxnode];//sum[i]==x表示第i个节点的次数为x,便于删除
int sz;//字典树一共有sz个节点,从0到sz-1标号
//初始化
void clear()
{
sz=1;
memset(ch[0],0,sizeof(ch[0]));//ch值为0表示没有儿子
memset(sum,0,sizeof(sum));
}
//在字典树中插入单词s,但是如果已经存在s单词会重复插入且覆盖权值
//所以insert前需要判断一下是否已经存在s单词了
void insert(string s)
{
int u=0,n=s.length();
for(int i=0;i<n;i++)///建立字典树
{
int id=s[i]-'a';
if(ch[u][id]==0)//无该儿子
{
ch[u][id]=sz;
memset(ch[sz],0,sizeof(ch[sz]));
val[sz++]=0;
}
u=ch[u][id];
sum[u]++;
}
val[u]=n;
}
//在字典树中查找单词s
bool find1(string s)
{
int n=s.length(),u=0;
for(int i=0;i<n;i++)
{
int id=s[i]-'a';
if(ch[u][id]==0)
return false;
u=ch[u][id];
}
return val[u];
}
int find2(string s)///查找前缀为s的个数
{
int n=s.length(),u=0;
for(int i=0;i<n;i++)
{
int id=s[i]-'a';
if(ch[u][id]==0)
return 0;
u=ch[u][id];
}
return sum[u];
}
void del(string s,int cnt) //删除前缀s的所有单词
{
int n=s.length(),u=0;
for(int i=0;i<n;i++)
{
int id=s[i]-'a';
if(ch[u][id]==0)
return ;
u=ch[u][id];
sum[u]-=cnt;
}
for(int i=0;i<26;i++)
ch[u][i]=0;
}
};
Trie trie;
int main()
{
int n;
while(scanf("%d",&n)!=-1)
{
trie.clear();
for(int i=1;i<=n;i++)
{
string s1,s2;
cin>>s1>>s2;
if(s1[0]=='i')
{
trie.insert(s2);
}
else if(s1[0]=='d')
{
trie.del(s2,trie.find2(s2));
}
else
{
if(trie.find2(s2)!=0)
{
printf("Yes\n");
}
else
printf("No\n");
}
}
}
return 0;
}