字典树板子
基本的操作
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 };
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 }
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 }
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 }
注意事项:
1.用G++交会出现Memory Limit Exceeded(就算释放了内存,还是Memory Limit Exceeded)
2.根结点要初始化root=new node;