字典树
来源:互联网 发布:谷歌看图软件下载 编辑:程序博客网 时间:2024/05/22 04:51
字典树,就是一种最大限度的利用单词的公共前缀高效查询单词(但不止是单词,所有有前缀的都可以类似进行查找)的数据结构。节点定义如下:
struct node
{
node *next[26];//26个字母,NULL则表示没有相应字母的分支
bool isWord;//true表示从根节点到当前节点路途中所有字母连成的单词已经在字典中
int point;//指向单词的信息域(如释义等)
node()//初始化函数
{
for(int i = 0;i < 26;i ++)
next[i] = NULL;
isWord = false;
point = 0;
}
}
二、POJ 3630、Phone List
struct node
{
node *next[26];//26个字母,NULL则表示没有相应字母的分支
bool isWord;//true表示从根节点到当前节点路途中所有字母连成的单词已经在字典中
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
/*poj 250317664K235MS*/#include<cstdio>#include<cstring>#include<iostream>#define MAXN 150005using 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]);elseprintf("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
/*poj 36304628K219MS*/#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define MAXN 100005using 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);//要先按字符串长度从小到大排序,不然对于 12 1之类的数据会出错 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 ;}}elsetmp->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;}
0 0
- 字典树
- 字典树
- 字典树
- 字典树
- 字典树
- 字典树。。
- 字典树
- 字典树
- 字典树
- 字典树
- 字典树
- 字典树
- 字典树
- 字典树
- 字典树
- 字典树
- 字典树
- 字典树
- .net(C#)页面之间传递参数的几种方法
- 菜鸟问题:EditText有下划线显示,去除下划线
- scrum项目管理
- HDU2492 Ping pong 树状数组求逆序数
- 股票接口
- 字典树
- 善用Condition设置,解决Source Insight中的parse too complex问题
- 操作系统——使用动态优先权的进程调度算法的模拟
- java 并发编程读书笔记
- java自学之路-----线程(3) String
- 设计模式入门之迭代器模式Iterator
- 【think in java】wait和sleep的区别
- Java 输出整数的二进制
- struts2 验证