【Trie(字典树)--模板】学习
来源:互联网 发布:淘宝答题秒杀辅助工具 编辑:程序博客网 时间:2024/05/21 09:05
今天早上学习字典树,学了一上午懂了思想。
一、儿子节点表示法
代码是学习大佬的,数组实现字典树;
next [ NODE ] [ 26 ] :
NODE是节点编号 ,后面26指的是每个节点都有26个分叉,if next[ i ] [ j ]==1 ,意思是说到 编号i的字母 到达 j 对应的字母 是 ok 的;
如果加上了算法头文件,则数组名为 next 会CE!
v [ NODE ] :
v 数组用来保存各节点的信息;
#define NODE 1000005int next[NODE][26];int v[NODE];int node;void init() //初始化;{ node=1; //节点个数; memset(next[0],0,sizeof(next[0]));}void add(char *str) //加入{ int cur=0,k; int len=strlen(str); for(int i=0;i<len;i++) { k=str[i]-'a'; if(next[cur][k]==0) { memset(next[node],0,sizeof(node)); v[node]=0; //清空操作; next[cur][k]=node++; } cur=next[cur][k]; v[cur]++; }}int cal(char *str) //查询{ int cur=0,k; int len=strlen(str); for(int i=0;i<len;i++) { k=str[i]-'a'; if(next[cur][k]) cur=next[cur][k]; else return 0; } return v[cur];}// 注意在这里v[ i ] 存的是到达 编号为 i 的这个节点次数;
可以对着下图模拟一波代码:
两个字符串nyoj 、nyist ,
二、左儿子右兄弟表示法
由于儿子节点表示法会将很多的节点白白浪费,耗用了大量的空间。左儿子右兄弟表示法以时间换空间节省内存,利用该表示法建成的是一棵二叉树,每个节点的左儿子节点代表儿子,右儿子节点表示兄弟;
代码:
#include<bits/stdc++.h>#define N 1010struct node{ char c; int l,r; int val,cut;}trie[N+10];int node;void init(){ node=1; memset(trie,0,sizeof(trie));}void add(char *s){ int rt,i; for(rt=0;*s;s++,rt=i) { for(i=trie[rt].l;i;i=trie[i].r) { if(trie[i].c==*s) break; } if(i==0) { trie[node].r=trie[rt].l; trie[node].l=0; trie[node].c=*s; trie[node].val++; trie[rt].l=node; i=node++; } } trie[rt].cut++; return 0;}int cal(char *s){ int rt; for(rt=0;*s;s++) { for(rt=trie[rt].l;rt;rt=trie[rt].r) { if(trie[rt].c==*s) break; } if(rt==0) return 0; } return ~;}
模拟这份代码的时候总搞不懂,比如nyoj,nyist构建二叉树的过程:
----------------------》
o节点被挤到i的右兄弟上了,明白了这一点就模拟好代码了;
三、01二叉树模板
题目类型 基本与异或相关,比如求序列两两亦或最大值、序列连续异或最大值等;
异或规则 是:相同为0,不同为1;
给定一个数x,为了得到异或后的最大值尽量寻找与 x 同位相异的数字,把数字转化为二进制串即01串,把这个串插入字典树中,要从高位开始插入,贪心思想!
代码:
int nex[N][2];int val[N],num[N];int node;void init(){ node=1; memset(nex[0],0,sizeof(nex[0]));}void add(int c){ int cur=0,k; for(int i=31;i<=0;i--) { k=(c>>i)&1; if(!nex[cur][k]) { memset(nex[node],0,sizeof(nex[node])); val[node]=cut[node]=0; nex[cur][k]=node++; } cur=nex[cur][k]; num[cur]++; } val[cur]=c;}int cal(int c){ int cur=0,k; for(int i=31;i<=0;i--) { k=(c>>i)&1; if(nex[cur][1-k]) //同位相异,1-0=1,1-1=0; cur=nex[cur][1-k]; else cur=nex[cur][k]; } return c^val[cur];}
小结:
经常保存的信息为:①某个节点用的次数 ②某个节点作为串的尾节点次数
阅读全文
0 0
- 【Trie(字典树)--模板】学习
- 字典树(trie)模板
- Trie(字典树模板)
- TRIE(字典树)模板
- trie树学习总结(字典树模板)
- 字典树(trie)模板
- Trie字典树【模板
- 字典树Trie 模板
- Trie - 字典树 模板
- Trie字典树模板
- trie树(字典树)模板
- trie树(字典树)--模板
- Trie树 字典树 模板
- 树学习 ---------字典树(Trie Tree)
- 【学习记录】trie树(字典树)
- Trie(字典树)学习小结1
- 字典树(trie树)模板: Phone List 问题
- 【模板】【字符串】Trie(前缀树、字典树)
- ContextLoaderListener作用详解
- 开源OkHttpUtils升级版OkGo,完美支持RxJava
- linux中的genewise怎么安装
- 老毛桃装系统
- C++将string转换为char
- 【Trie(字典树)--模板】学习
- <script>标签的for属性和event属性
- POJ
- log4j2.8和springboot搭配使用时的xwEx问题
- web项目中利用js插件生成二维码
- A
- HDU-6069 Counting Divisors
- zabbix客户端设置
- JDK切换版本报错问题