Problem C (字典树的查找删除和插入)2016"百度之星" - 资格赛(Astar Round1)

Problem C

Accepts: 630

Submissions: 5255

Time Limit: 2000/1000 MS (Java/Others)

Memory Limit: 131072/131072 K (Java/Others)

Problem Description

度熊手上有一本神奇的字典,你可以在它里面做如下三个操作:

1、insert : 往神奇字典中插入一个单词

2、delete: 在神奇字典中删除所有前缀等于给定字符串的单词

3、search: 查询是否在神奇字典中有一个字符串的前缀等于给定的字符串

Input

这里仅有一组测试数据。第一行输入一个正整数N
(1\leq N\leq 100000)N(1≤N≤100000),代表度熊对于字典的操作次数,接下来NN行,每行包含两个字符串,中间中用空格隔开。第一个字符串代表了相关的操作(包括:
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;
}
时间: 2025-01-02 11:23:46

Problem C (字典树的查找删除和插入)2016"百度之星" - 资格赛(Astar Round1)的相关文章

2016&quot;百度之星&quot; - 资格赛(Astar Round1)-(模拟+线段树+乘法逆元)

Problem A Accepts: 1351 Submissions: 9951 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Problem Description 度熊手上有一本字典存储了大量的单词,有一次,他把所有单词组成了一个很长很长的字符串.现在麻烦来了,他忘记了原来的字符串都是什么,神奇的是他竟然记得原来那些字符串的哈希值.一个字符串的哈希值,由以下公式计算得到: H

hdu 5685 Problem A(2016&quot;百度之星&quot; - 资格赛(Astar Round1)——线段树)

题目链接:acm.hdu.edu.cn/showproblem.php?pid=5685 Problem A Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 564    Accepted Submission(s): 236 Problem Description 度熊手上有一本字典存储了大量的单词,有一次,他把所有单词组成了一个很长

2016&quot;百度之星&quot; - 资格赛(Astar Round1) Problem D 简单题

Problem D Accepts: 1527 Submissions: 4307 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Problem Description 度熊所居住的 D 国,是一个完全尊重人权的国度.以至于这个国家的所有人命名自己的名字都非常奇怪.一个人的名字由若干个字符组成,同样的,这些字符的全排列的结果中的每一个字符串,也都是这个人的名字.例如,如果一个人名字

2016&quot;百度之星&quot; - 资格赛(Astar Round1) Problem C (Trie树)

题意:对单词根据前缀进行插入,插入,和查询操作,查询的话存在即可. 因为之前几乎没怎么做过类似的题,再加上这次做的时候,对题意理解的不到位,所以错了很多次,以后要先把题意理解透彻再敲代码,这样会避开之后修改的很多不必要的细节错误. 思路:Trie树,root根节点通过next指针数组连接着26个相同的结点,分别代表26个英文字母,对应着第一个字母,同理,之后的字母也这么建立.这样树形结构就出来了.结构体里的num为记录以当前字符串为前缀的单词的数目. (1)insertNode:插入单词,如果之

[HDU5687]2016&quot;百度之星&quot; - 资格赛 Problem C

题目大意:有n个操作,每个操作是以下三个之一,要你实现这些操作. 1.insert : 往字典中插入一个单词2.delete: 在字典中删除所有前缀等于给定字符串的单词3.search: 查询是否在字典中有一个字符串的前缀等于给定的字符串 解题思路:Trie树即可. 注意代码第49行的判断,我当时以为只要成功搜到这个前缀就一定有答案,忽略了删除操作使某些前缀的单词数为0的情况. C++ Code: #include<cstdio> struct node{ int cnt; node* nxt

Problem A(逆元) 2016&quot;百度之星&quot; - 资格赛(Astar Round1)

Problem A Accepts: 1515 Submissions: 10832 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Problem Description 度熊手上有一本字典存储了大量的单词,有一次,他把所有单词组成了一个很长很长的字符串.现在麻烦来了,他忘记了原来的字符串都是什么,神奇的是他竟然记得原来那些字符串的哈希值.一个字符串的哈希值,由以下公式计算得到:

Hdu 5696 区间价值(2016百度之星初赛Astar Round2B )(线段树)

思路来源于:http://blog.csdn.net/kk303/article/details/51479423 注意数组用 long long 存,否则WA. /* Problem : Status : By wf, */ #include "algorithm" #include "iostream" #include "cstring" #include "cstdio" #include "string&q

Problem B 2016&quot;百度之星&quot; - 资格赛(Astar Round1)

Problem B Accepts: 2037 Submissions: 7572 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Problem Description 度熊面前有一个全是由1构成的字符串,被称为全1序列.你可以合并任意相邻的两个1,从而形成一个新的序列.对于给定的一个全1序列,请计算根据以上方法,可以构成多少种不同的序列. Input 这里包括多组测试数据,每组测

[HDU5685]2016&quot;百度之星&quot; - 资格赛 Problem A

题目大意:给你一个字符串,和一些问题,每个问题问你[l,r]子串的哈希值是多少. 哈希值计算方法为:$H(s)=\prod _{i=1} ^{i\leq len(s)}(s_i-28)(mod\ 9973)$. 其中$s_i$代表 S[i] 字符的 ASCII 码. 解题思路:我们知道,要算区间[l,r]所有的和,就可以用$O(n)$的时间预处理出数组t,令$t[i]$表示前i个数的和,那么$t[r]-t[l-1]$即为区间[l,r]所有之和,询问时间复杂度$O(1)$,这就是维护前缀和的做法.