题意:对单词根据前缀进行插入,插入,和查询操作,查询的话存在即可。
因为之前几乎没怎么做过类似的题,再加上这次做的时候,对题意理解的不到位,所以错了很多次,以后要先把题意理解透彻再敲代码,这样会避开之后修改的很多不必要的细节错误。
思路:Trie树,root根节点通过next指针数组连接着26个相同的结点,分别代表26个英文字母,对应着第一个字母,同理,之后的字母也这么建立。这样树形结构就出来了。结构体里的num为记录以当前字符串为前缀的单词的数目。
(1)insertNode:插入单词,如果之前这样的前缀并不存在,为其分配结点即可,如果已经存在,计数器 + 1。
(2)delNode:删除单词,找到对应的前缀之后,使其计数器清零,或者删除节点都行,*但是删除之前应该记录计数器的数值,因为删除了以此为前缀的单词,前面的前缀对应的计数器也应该减少(全局变量temp就是用来记录这个值的,以便于之后的操作中使之前的前缀减去这个值)*因为这个错了很多次QAQ。
(3)delNum:有delNode删除完单词之后调用,使这个单词之前的前缀对应的num值同样减少temp。
eg:删除了以abc为前缀的单词 2 个,temp为 2,那么分别以a, b为前缀的单词数目同样减少temp。
(4)searchNode:查询操作,找到以str2数组为前缀的num值,如果其>0,即输出"Yes",反之,"No"。
Problem Description
度熊手上有一本神奇的字典,你可以在它里面做如下三个操作:
1、insert : 往神奇字典中插入一个单词
2、delete: 在神奇字典中删除所有前缀等于给定字符串的单词
3、search: 查询是否在神奇字典中有一个字符串的前缀等于给定的字符串
Input
这里仅有一组测试数据。第一行输入一个正整数N(1≤N≤100000)N (1\leq N\leq 100000)N(1≤N≤100000),代表度熊对于字典的操作次数,接下来NNN行,每行包含两个字符串,中间中用空格隔开。第一个字符串代表了相关的操作(包括: insert, delete 或者 search)。第二个字符串代表了相关操作后指定的那个字符串,第二个字符串的长度不会超过30。第二个字符串仅由小写字母组成。
Output
对于每一个search 操作,如果在度熊的字典中存在给定的字符串为前缀的单词,则输出Yes 否则输出 No。
Sample Input
Copy
5 insert hello insert hehe search h delete he search hello
Sample Output
Copy
Yes No
贴上代码(这是比赛时候改了很多次的代码,写的很乱,如果题目拉入杭电OJ的话,我会再改一改):
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <algorithm> #define N 26 using namespace std; struct node { char c; int num; struct node *next[N]; }; int temp; struct node *root; char str1[60], str2[60]; struct node *createNode() { struct node *p = (struct node *)malloc(sizeof(struct node)); p -> num = 1; for(int i = 0; i < N; i++) p -> next[i] = NULL; return p; } void delNum(struct node *r, int n) { int cur = str2[n] - ‘a‘; if(r -> next[cur] == NULL || r -> next[cur] -> num == 0 || n >= strlen(str2) - 1) { return ; } if(r -> next[cur] -> num >= temp) r -> next[cur] -> num -= temp; else r -> next[cur] -> num = 0; delNum(r -> next[cur], n + 1); } struct node *insertNode(struct node *r, int n) { int cur = str2[n] - ‘a‘; if(n >= strlen(str2)) { return r; } struct node *p = r -> next[cur]; if(r -> next[cur] == NULL) { r -> next[cur] = createNode(); } else { (r -> next[cur] -> num)++; } //printf("%d", r -> next[cur] -> num); insertNode(r -> next[cur], n + 1); return r; } struct node *delNode(struct node *r, int n) { int cur = str2[n] - ‘a‘; struct node *p = r -> next[cur]; if(n >= strlen(str2) - 1) { //if(r -> next[cur] != NULL) //printf("%d", r -> next[cur] -> num); if(r -> next[cur] != NULL) { temp = r -> next[cur] -> num; r -> next[cur] -> num = 0; r -> next[cur] = NULL; delNum(root, 0); } return r; } if(r -> next[cur] == NULL || r -> next[cur] -> num == 0) return r; //printf("%d", r -> next[cur] -> num); delNode(r -> next[cur], n + 1); return r; } int searchNode(struct node *r, int n) { int cur = str2[n] - ‘a‘; struct node *p = r -> next[cur]; if(r -> next[cur] == NULL || r -> next[cur] -> num == 0) return 0; if(n >= strlen(str2) - 1) { //printf("%d", r -> next[cur] -> num); if(r -> next[cur] == NULL || r -> next[cur] -> num == 0) return 0; if(r -> next[cur] -> num >= 1) return 1; else return 0; } //printf("%d", r -> next[cur] -> num); return searchNode(r -> next[cur], n + 1); } int main() { int n; root = createNode(); scanf("%d", &n); for(int i = 0; i < n; i++) { scanf("%s%s", str1, str2); if(str1[0] == ‘d‘) { delNode(root, 0); } else if(str1[0] == ‘i‘) { insertNode(root, 0); } else { if(searchNode(root, 0) == 1) printf("Yes\n"); else printf("No\n"); } } return 0; }