字典树,就是一种最大限度的利用单词的公共前缀高效查询单词(但不止是单词,所有有前缀的都可以类似进行查找)的数据结构。节点定义如下:
1 2 3 4 5 6 7 8 9 10 11 12 13
| struct node { node *next[26]; bool isWord; int point; node() { for(int i = 0;i < 26;i ++) next[i] = NULL; isWord = false; point = 0; } }
|
建树和查询都非常方便,删除操作并不常用,比较偷懒的方法就是找到待删除单词的最后一个字母所在节点,把isWord标记置为false即可。代码就不给出了。
需要注意的是,在实际建树过程中,如果动态分配空间无论是new还是malloc都会很慢,一般都会TLE的,所以代码都是静态实现,即先分配一定的空间,需要用新节点时就从空间里拿。
例题:
一、POJ 2503 Babelfish
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
|
#include<cstdio> #include<cstring> #include<iostream>
#define MAXN 150005
using namespace std;
struct node { node *next[26]; bool isWord; int point; node() { for(int i = 0;i < 26;i ++) next[i] = NULL; isWord = false; point = 0; } }all[MAXN];
int index = 1,size; char store[100005][11];
void insert(char *str1,char *str2) { node *tmp = &all[0]; int len = strlen(str1); for(int i = 0;i < len;i ++) { int num = str1[i] - 'a'; if(!tmp->next[num]) tmp->next[num] = &all[index++]; tmp = tmp->next[num]; } tmp->isWord = true; size ++; tmp->point = size; strcpy(store[size] , str2); }
void find(char *s) { node *tmp = &all[0]; int len = strlen(s); for(int i = 0;i < len;i ++) { int num = s[i] - 'a'; if(!tmp->next[num]) { printf("eh\n"); return ; } tmp = tmp->next[num]; } if(tmp->isWord) printf("%s\n",store[tmp->point]); else printf("eh\n"); }
int main() { char str1[12] = {0},str2[12] = {0},s[24]; while(gets(s) && s[0]) { sscanf(s,"%s %s",str1,str2); insert(str2,str1); } while(scanf("%s",s) != EOF) { find(s); } return 0; }
|
二、POJ 3630、Phone List
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
|
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm>
#define MAXN 100005
using namespace std;
struct alp { char s[11]; }per[MAXN / 10 + 5];
struct node { bool isWord; node *next[10]; node() { isWord = false; for(int i = 0;i < 10;i ++) next[i] = NULL; } }all[MAXN];
bool cmp(alp a,alp b) { return strlen(a.s) < strlen(b.s); }
void doIt() { memset(all , 0 , sizeof(all)); int n,index = 0; cin>>n; node *root, *tmp; root = &all[index++]; for(int i = 1;i <= n;i ++) scanf("%s",per[i].s); sort(per + 1 , per + n + 1 , cmp); for(int p = 1;p <= n;p ++) { tmp = root; int len = strlen(per[p].s); for(int i = 0;i < len;i ++) { int num = per[p].s[i] - '0'; if(tmp->next[num]) { if(tmp->next[num]->isWord) { printf("NO\n"); return ; } } else tmp->next[num] = &all[index++]; tmp = tmp->next[num]; } tmp->isWord = true; } printf("YES\n"); return ; }
int main() { int T; cin>>T; while(T --) { doIt(); } return 0; }
|