度熊手上有一本神奇的字典,你可以在它里面做如下三个操作: 1、insert : 往神奇字典中插入一个单词 2、delete: 在神奇字典中删除所有前缀等于给定字符串的单词 3、search: 查询是否在神奇字典中有一个字符串的前缀等于给定的字符串
Input这里仅有一组测试数据。第一行输入一个正整数 N(1≤N≤100000),代表度熊对于字典的操作次数,接下来 N行,每行包含两个字符串,中间中用空格隔开。第一个字符串代表了相关的操作(包括: insert, delete 或者 search)。第二个字符串代表了相关操作后指定的那个字符串,第二个字符串的长度不会超过30。第二个字符串仅由小写字母组成。Output对于每一个search 操作,如果在度熊的字典中存在给定的字符串为前缀的单词,则输出Yes 否则输出 No。Sample Input
5insert helloinsert hehesearch hdelete hesearch helloSample Output
YesNo 思路分析 : 字典树板子题,唯一有个要注意的地方就是删除操作,你要删除具有公共前缀的所有串,首先可以先计算出公共前缀的个数,然后再去处理一遍所要处理的串,给每个节点删除掉公共前缀的个数, 将最后一个点的 val 变为 0 ,并且将其 next 全部变为 0即可。 代码示例 :
#define ll long longconst int maxn = 1e6+5;const double pi = acos(-1.0);const int inf = 0x3f3f3f3f;struct node{ int next[26]; int val;}t[maxn];char f[20], s[50];int rt = 1;int num;void insert() { int u = 0, v; int len = strlen(s+1); for(int i = 1; i <= len; i++){ v = s[i] - 'a'; if (!t[u].next[v]) t[u].next[v] = rt++; u = t[u].next[v]; t[u].val++; } }void del() { int u = 0, v; int len = strlen(s+1); for(int i = 1; i <= len; i++){ v = s[i] - 'a'; u = t[u].next[v]; t[u].val -= num; } t[u].val = 0; for(int j = 0; j < 26; j++) t[u].next[j] = 0;}int search() { int u = 0, v; int len = strlen(s+1); for(int i = 1; i <= len; i++){ v = s[i] - 'a'; if (!t[u].next[v]) return 0; u = t[u].next[v]; //if (t[u].val == 0) return 0; } return t[u].val;}int main() { //freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout); int n; cin >> n; memset(t, 0, sizeof(t)); while(n--){ scanf("%s%s", f+1, s+1); if (f[1] == 'i') insert(); else if (f[1] == 'd') {num = search(); if (num != 0) del();} else { if (search()) cout << "Yes" << endl; else cout << "No" << endl; } } return 0;}