反思:之前在删除单词的时候,只是删除掉单词前缀以后的字符,而没有把整个单词都删除掉,导致WA了很多次。
高手请略过...
AC代码:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string.h>
using namespace std;struct Dic {Dic *nt[26];//指向下一个字符的指针int num;//重叠字符出现的个数Dic() {num = 1;//明显,初始化的时候,字符就为1个for (int i = 0; i < 26; i++)nt[i] = NULL;}
};void insert(Dic *root, char *str) {int len = strlen(str);int pos;Dic *p = root;for (int i = 0; i < len; i++) {pos = str[i] - 'a';if (p->nt[pos] == NULL) p->nt[pos] = new Dic;//字典中不存在这个字符,则插入一个新的结点else p->nt[pos]->num++;//如果该字符存在,则该结点的重叠个数+1p = p->nt[pos];}
}bool search(Dic *root, char *str) {int len = strlen(str);int pos;Dic *p = root;for (int i = 0; i < len; i++) {pos = str[i] - 'a';if (p->nt[pos] == NULL)return false;p = p->nt[pos];}return true;
}void Del(Dic *root, char *str) {Dic *pre = NULL, *p = root;int len = strlen(str);int pos, sum;//遍历到前缀的最后一个字符for (int i = 0; i < len; i++) {pos = str[i] - 'a';if (p->nt[pos] == NULL)return;p = p->nt[pos];}sum = p->num;//拥有这个前缀的单词的个数p = root;for (int i = 0; i < len; i++) {pos = str[i] - 'a';pre = p;//记录前一个结点,方便删除p = p->nt[pos];p->num -= sum; //因为要删除“拥有这个前缀单词”,所以就需要在树上减去 “拥有这个前缀的单词的个数”if (p->num == 0) //如果为0,则表明:拥有这个前缀的单词都不存在了,所以直接赋值为NULLpre->nt[pos] = NULL;}
}int main() {int N;Dic *root = new Dic;cin >> N;while (N--) {char order[10], str[31];scanf("%s %s", order, str);if (order[0]=='i') {insert(root, str);}else if (order[0] == 'd') {Del(root, str);}else if (order[0] == 's') {if (search(root, str)) printf("Yes\n");else printf("No\n");}}return 0;
}