Problem C
Problem Description
度熊手上有一本神奇的字典,你可以在它里面做如下三个操作:
1、insert : 往神奇字典中插入一个单词
2、delete: 在神奇字典中删除所有前缀等于给定字符串的单词
3、search: 查询是否在神奇字典中有一个字符串的前缀等于给定的字符串
Input
这里仅有一组测试数据。第一行输入一个正整数,代表度熊对于字典的操作次数,接下来
行,每行包含两个字符串,中间中用空格隔开。第一个字符串代表了相关的操作(包括: insert, delete 或者 search)。第二个字符串代表了相关操作后指定的那个字符串,第二个字符串的长度不会超过30。第二个字符串仅由小写字母组成。
Output
对于每一个search 操作,如果在度熊的字典中存在给定的字符串为前缀的单词,则输出Yes 否则输出 No。
Sample Input
5
insert hello
insert hehe
search h
delete he
search hello
Sample Output
Copy
Yes
No
Statistic | Submit | Clarifications | Back
Trie 字典树模拟
有几个提示
1.自己是自己的前缀
2.插入和删除的时候是单词 查找的时候是字符串
AC代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct Trie
{
//对应26个小写英文字母
Trie *word[26];
//计算次数
int time;
Trie()
{
time=0;
for(int i=0;i<26;i++)
word[i]=NULL;
}
};
//建树
void build(Trie *root,char *str)
{
for(str;*str;str++)
{
if(!root->word[*str-'a'])
{
root->word[*str-'a']=new Trie();
}
root->word[*str-'a']->time++;
root=root->word[*str-'a'];
}
}
//删除
void del(Trie *root,char *str)
{
Trie *head,*pre;
head=root;
int num,i;
for(i=0;str[i]!='\0';i++)
{
if(root->word[str[i]-'a'])
{
pre=root;
num=root->word[str[i]-'a']->time;
root=root->word[str[i]-'a'];
}
else
break;
}
if(str[i]=='\0')
{
//回收需要删除的节点
free(pre->word[str[i-1]-'a']);
//置为NULL 防止出现野指针
pre->word[str[i-1]-'a']=NULL;
for(int i=0;str[i]!='\0';i++)
{
if(head->word[str[i]-'a']!=NULL)
{
head->word[str[i]-'a']->time-=num;
head=head->word[str[i]-'a'];
}
}
}
}
//查找
bool search(Trie *root,char *str)
{
int i;
for(i=0;str[i]!='\0';i++)
{
if(root->word[str[i]-'a'])
root=root->word[str[i]-'a'];
else
break;
}
if(str[i]=='\0')
{
// 如果次数大于0 证明为单词的前缀
if(root->time>0)
return true;
}
return false;
}
int main()
{
int n;
Trie *root=new Trie();
scanf("%d",&n);
for(int i=0;i<n;i++)
{
char order[10];
char str[35];
scanf("%s %s",order,str);
if(strcmp(order,"insert")==0)
{
build(root,str);
}
if(strcmp(order,"delete")==0)
{
del(root,str);
}
if(strcmp(order,"search")==0)
{
if(search(root,str))
puts("Yes");
else
puts("No");
}
}
return 0;
}