字典树算法详解


字典树,又称单词查找树,Trie树,是一种树形结构,哈希表的一个变种。用于统计,排序和保存大量的字符串(也可以保存其的)。
优点就是利用公共的前缀来节约存储空间。在这举个简单的例子:比如说我们想储存3个单词,nyist、nyistacm、nyisttc。如果只是
单纯的按照以前的字符数组存储的思路来存储的话,那么我们需要定义三个字符串数组。但是如果我们用字典树的话,只需要定义
一个树就可以了。在这里我们就可以看到字典树的优势了。
)

基本的操作

定义(即定义结点)

struct node{  
    int cnt;  
    struct node *next[26];  
    node(){  
        cnt=0;  
        memset(next,0,sizeof(next));  
    }  
};

next是表示每层有多少种类的数,如果只是小写字母,则26即可,若改为大小写字母,则是52,若再加上数字,则是62了,这里根据题意来确定。
cnt可以表示一个字典树到此有多少相同前缀的数目,这里根据需要应当学会自由变化。

插入(即建树过程)

构建Trie树的基本算法也很简单,无非是逐一把每则单词的每个字母插入Trie。插入前先看前缀是否存在。如果存在,就共享,否则
创建对应的节点和边。比如要插入单词add(已经插入了单词“ad”),就有下面几步:

  • 考察前缀"a",发现边a已经存在。于是顺着边a走到节点a。
  • 考察剩下的字符串"dd"的前缀"d",发现从节点a出发,已经有边d存在。于是顺着边d走到节点ad
  • 考察最后一个字符"d",这下从节点ad出发没有边d了,于是创建节点ad的子节点add,并把边ad->add标记为d。
void buildtrie(char *s){  
    node *p = root;  
    node *tmp = NULL;  
    int l = strlen(s);  
    for(int i = 0; i < l; ++i){  
        if(p->next[s[i]-'a'] == NULL){  
            tmp = new node;  
            p->next[s[i]-'a'] = tmp;  
        }  
        p = p->next[s[i]-'a'];  
        p->cnt++;  
    }  
}

查找

1、每次从根结点开始进行搜索;
2、取要查找关键词的第一个字母,并根据该字母选择对应的子树并转到该子树继续进行检索;
3、在相应的子树上,取得要查找关键词的第二个字母,并进一步选择对应的子树进行检索; 
4、迭代刚才过程。。。
5、直到在某个结点处:
——关键词的所有字母都被取出,则读取附在该结点上的信息,即完成查找。
——该结点没有任何信息,则输出该关键词不在此字典树里。

void findtrie(char *s){  
    node *p = root;  
    int l = strlen(s);  
    for(int i = 0; i < l; ++i){
        if(p->next[s[i]-'a'] == NULL){
            printf("0\n");  
            return;  
        }  
        p = p->next[s[i]-'a'];  
    }
    printf("%d\n",p->cnt);  
}

释放内存

有些题目,数据比较大,需要查询完之后释放内存(比如:hdu1671 Phone List)
递归释放内存:

void del(node *root) {
    for (int i = 0; i < 26; i++)
        if (root->next[i])
            del(root->next[i]);
    delete (root);
}

注意事项

1.用G++交会出现Memory Limit Exceeded(就算释放了内存,还是Memory Limit Exceeded)
2.根结点要初始化root=new node;

练习

hdu 1251 统计难题
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1251
解题思路:http://blog.csdn.net/piaocoder/article/details/41552691
hdu 2072 单词数
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2072
解题思路:http://blog.csdn.net/piaocoder/article/details/41902793
hdu 1671 Phone List
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1671
解题思路:http://blog.csdn.net/piaocoder/article/details/47951011
POJ 2001 Shortest Prefixes
题目链接:http://poj.org/problem?id=2001
解题思路:http://blog.csdn.net/piaocoder/article/details/47731321
POJ 2418 Hardwood Species
题目链接:http://poj.org/problem?id=2418
解题思路:http://blog.csdn.net/piaocoder/article/details/47731453
POJ 2503 Babelfish
题目链接:http://poj.org/problem?id=2503
解题思路:http://blog.csdn.net/piaocoder/article/details/47731701

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值