字典树板子

基本的操作

1.定义(即定义结点)

 

next是表示每层有多少种类的数,如果只是小写字母,则26即可,若改为大小写字母,则是52,若再加上数字,则是62了,这里根据题意来确定。

cnt可以表示一个字典树到此有多少相同前缀的数目,这里根据需要应当学会自由变化。

1 struct node{  
2     int cnt;  
3     struct node *next[26];  
4     node(){  
5         cnt=0;  
6         memset(next,0,sizeof(next));  
7     }  
8 }; 
View Code

2.插入(即建树过程)

 

构建Trie树的基本算法也很简单,无非是逐一把每则单词的每个字母插入Trie。插入前先看前缀是否存在。如果存在,就共享,否则

 

创建对应的节点和边。比如要插入单词add(已经插入了单词“ad”),就有下面几步:

 

    考察前缀"a",发现边a已经存在。于是顺着边a走到节点a。

 

    考察剩下的字符串"dd"的前缀"d",发现从节点a出发,已经有边d存在。于是顺着边d走到节点ad

 

    考察最后一个字符"d",这下从节点ad出发没有边d了,于是创建节点ad的子节点add,并把边ad->add标记为d。

 

 1 <pre name="code" class="cpp">void buildtrie(char *s){  
 2     node *p = root;  
 3     node *tmp = NULL;  
 4     int l = strlen(s);  
 5     for(int i = 0; i < l; ++i){  
 6         if(p->next[s[i]-'a'] == NULL){  
 7             tmp = new node;  
 8             p->next[s[i]-'a'] = tmp;  
 9         }  
10         p = p->next[s[i]-'a'];  
11         p->cnt++;  
12     }  
13 }
View Code

3.查找

1)每次从根结点开始进行搜索;

(2)取要查找关键词的第一个字母,并根据该字母选择对应的子树并转到该子树继续进行检索;

 

(3)在相应的子树上,取得要查找关键词的第二个字母,并进一步选择对应的子树进行检索; 

 

(4)迭代刚才过程。。。

 

(5)直到在某个结点处:

 

——关键词的所有字母都被取出,则读取附在该结点上的信息,即完成查找。

 

——该结点没有任何信息,则输出该关键词不在此字典树里。

 

 1 void findtrie(char *s){  
 2     node *p = root;  
 3     int l = strlen(s);  
 4     for(int i = 0; i < l; ++i){
 5         if(p->next[s[i]-'a'] == NULL){
 6             printf("0\n");  
 7             return;  
 8         }  
 9         p = p->next[s[i]-'a'];  
10     }
11     printf("%d\n",p->cnt);  
12 }
View Code

4.释放内存

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

1 void del(node *root){
2     for(int i = 0; i < 10; ++i)
3         if(root->next[i])
4             del(root->next[i]);
5     delete(root);
6 }
View Code

注意事项:

1.用G++交会出现Memory Limit Exceeded(就算释放了内存,还是Memory Limit Exceeded)

2.根结点要初始化root=new node; 

 

posted @ 2019-10-26 23:00  ljy3268  阅读(212)  评论(0编辑  收藏  举报