字典树

来源:互联网 发布:谷歌看图软件下载 编辑:程序博客网 时间: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;
    }
}

如图(图片来源:百度百科)


建树和查询都非常方便,删除操作并不常用,比较偷懒的方法就是找到待删除单词的最后一个字母所在节点,把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
原创粉丝点击