2016"百度之星" - 资格赛(Astar Round1) Problem C
字典树。
插入的时候update一下节点出现的次数。
delete的时候,先把前缀之后的全删了。然后看前缀最后一个节点出现了几次,然后前缀上每个节点的次数都减去这个次数。
前缀从上到下再检查一遍,如果出现了次数为0的节点,也删去。
#include <stdio.h> #include <math.h> #include<cstring> #include<cmath> #include<map> #include<string> #include<algorithm> using namespace std; struct Node { int val; int f[27]; } node[4000000]; int root,n; char op[10], s[35]; int tot; int newnode() { ++tot; node[tot].val=0; for(int i=0; i<26; i++) node[tot].f[i]=-1; return tot; } void Insert() { int p=root; for(int i=0; s[i]; i++) { if(node[p].f[s[i]-'a']==-1) node[p].f[s[i]-'a']=newnode(); p=node[p].f[s[i]-'a']; node[p].val++; } } void Delete() { int p=0; bool Find=0; for(int i=0; s[i]; i++) { if(node[p].f[s[i]-'a']==-1) { Find=1; break; } p=node[p].f[s[i]-'a']; } if(Find==1) return; for(int i=0; i<26; i++) node[p].f[i]=-1; int Val=node[p].val; p=root; for(int i=0; s[i]; i++) { p=node[p].f[s[i]-'a']; node[p].val=node[p].val-Val; } p=0; for(int i=0; s[i]; i++) { int tmp=node[p].f[s[i]-'a']; if(node[tmp].val==0) { node[p].f[s[i]-'a']=-1; break; } p=node[p].f[s[i]-'a']; } } void Search() { int p=root; bool flag=0; for(int i=0; s[i]; i++) { if(node[p].f[s[i]-'a']==-1) { flag=1; break; } p=node[p].f[s[i]-'a']; } if(flag) printf("No\n"); else printf("Yes\n"); } int main() { while(~scanf("%d",&n)) { tot=0; root=0; for(int i=0; i<26; i++) node[root].f[i]=-1; for(int i=1; i<=n; i++) { scanf("%s%s",op,s); if(strcmp(op,"insert")==0) Insert(); else if(strcmp(op,"delete")==0) Delete(); else if(strcmp(op,"search")==0) Search(); } } return 0; }