字典树模板
2016-05-16 19:22
399 查看
字典树
字典树模板
1 模板一
2 模板二
题目链接I
题目链接II
题目链接III
竞赛时应该采用数组形式来写,易查错
详细讲解
1.模板
1.1 模板一
struct Node { int v; Node *next[M]; }*root; void Creat(char *s) //分配内存最好使用calloc 因为会进行初始化 而malloc不初始化 都是随机的数据垃圾 { int len = strlen(s); Node *p = root, *q; for(int i=0; i<len; i++) { int id = s[i] - 'a'; if(p->next[id] == NULL) { q = (Node *)calloc(1, sizeof(Node)); q->v = 1; p->next[id] = q; p = q; } else { p = p->next[id]; p->v++; } } p->v = -1; //标志最后一个为-1 } int Find(char *s) //查找函数可更具需要修改 { int len = strlen(s); Node *p = root; for(int i=0; i<len; i++) { int id = s[i] - 'a'; p = p->next[id]; if(p == NULL) return 0; //不存在 if(p->v == -1) return -1;//已有串是此串前缀 } return 1;// 此串是某已有串的前缀 }
1.2 模板二
tree[i][j]表示节点i的那个编号为j的子节点
int top;// top 表示节点个数 int tree[M][27]; // 字典树 int val[M]; //可赋予意义 例如为字符串的权值 当val[i] 大于0时i是单词节点 //或者记录某个节点出现的次数 void init() { top=1; memset(tree[0],0,sizeof tree[0]); } void insert(char *s, int v)//v 表示该单词权值信息 { int Len=strlen(s); int u=0; for(int i=0;i<Len;i++) { int c=s[i] - 'a'; if(!tree[u][c]) { memset(tree[top], 0, sizeof tree[top]) val[top]=0; tree[u][c]=top++; } u=tree[u][c]; } val[u]=v;//这里表示该值为单词节点 }
2.题目链接I
#include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> using namespace std; char s[1005][21]; struct node { int cnt; node *next[27]; }*root; void maketree(char *str) { int ans,len; node *p,*q;//设置两个临时指针 p=root; len=strlen(str); for(int i=0;i<len;i++) { ans=str[i]-'a';//用来记录不同字符 if(p->next[ans]!=NULL) { p=p->next[ans];//表示不同节点的值 p->cnt++; } else { q=(node *)calloc(1,sizeof(node));//申请新的节点 p->next[ans]=q; p=q; p->cnt=1; } } } void findtree(char *str) { int ans,len; node *p; p=root; len=strlen(str); for(int i=0;i<len;i++) { ans=str[i]-'a'; p=p->next[ans]; printf("%c",str[i]); if(p->cnt==1) break; } cout<<endl; } int main() { int n=0; root=(struct node *)calloc(1,sizeof(node));//为将要建立的链表申请一个新节点 while(~scanf("%s",s )) { maketree(s[n++]); if(n==12) break; } for(int i=0;i<n;i++) { printf("%s ",s[i]); findtree(s[i]); } }
3.题目链接II
I.#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define MOD 998244353 #define M 2000010 using namespace std; int top;// top 表示节点个数 int tree[M][4]; // 字典树 int val[M]; //字符串的权值 当val[i] 大于0时i是单词节点 void init() { top=1; memset(tree, 0, sizeof tree); memset(val, 0, sizeof val); } void insert(int v) { int u = 0;//根节点 for(int i = 0; i < 30 ; i++) { int t = v & ( 1<< i ); if(t) t = 1; if(!tree[u][t]) { val[top] = 1; tree[u][t] = top++; } else { val[tree[u][t]]++; } u = tree[u][t]; } } int ans; void find(int v) { int u = 0; for(int i = 0; i < 30; i++) { int t = v & (1 << i); if(t) t = 1; if(tree[u][t ^ 1]) ans = ( ans + (val[tree[u][t ^ 1]]) * (1 << i)) % MOD; u = tree[u][t] ; } } int a[M]; int main() { int T, n; scanf("%d", &T); int kase = 0; while(T--) { init(); ans = 0; scanf("%d", &n); for(int i=0; i<n; i++) { scanf("%d", &a[i]); insert(a[i]); } for(int i=0; i<n; i++) find(a[i]); printf("Case #%d: %d\n", ++kase, ans); } return 0; }
II.
#include <iostream> #include <cstdio> #include <cstdlib> using namespace std; #define maxn 50005 const int M = 2; const int MOD = 998244353; int a[maxn]; struct Node { int cnt; Node *next[M]; }*root; void insert(int v) { Node *p = root, *q; for(int i=0; i<30; i++) { int t = v&(1<<i); if(t) t = 1; if(p->next[t] == NULL) { q = (Node*)calloc(1, sizeof(Node)); q->cnt = 1; p->next[t] = q; p = q; } else { p = p->next[t]; p->cnt++; } } } int ans; void find(int v) { Node *p = root; for(int i=0; i<30; i++) { int t = v&(1<<i); if(t) t = 1; if(p->next[t^1]) { ans = (ans + (p->next[t^1]->cnt) * (1<<i)) % MOD; } p = p->next[t]; } } int kase = 0; int main() { int T, n; scanf("%d", &T); while(T--) { ans = 0; root = (Node*)calloc(1, sizeof(Node)); scanf("%d", &n); for(int i=0; i<n; i++) { scanf("%d", &a[i]); insert(a[i]); } for(int i=0; i<n; i++) find(a[i]); printf("Case #%d: %d\n", ++kase, ans); } return 0; }
4.题目链接III
#include <cstdio> #include <cstring> #include <iostream> using namespace std; #define maxn 400000 + 10 #define M 300000 + 10 #define mod 20071027 int tree[maxn][27], val[maxn], top; int d[maxn]; char s[M], tmp[105]; void init() { top = 1; memset(tree[0], 0, sizeof tree[0]); memset(d, 0, sizeof d); } void insert(char *s, int v) { int len = strlen(s), u = 0; for(int i = 0; i < len; i++) { int c = s[i] - 'a' ; if(!tree[u][c]) { memset(tree[top], 0, sizeof tree[top]); val[top] = 0; tree[u][c] = top++; } u = tree[u][c]; } val[u] = v; } int len ; int query(char *s, int pos) { int u = 0; int res = 0; for(int i = pos; i < len; i++) { int c = s[i] - 'a' ; u = tree[u][c]; if(!u) return res; if(val[u]) { res = (res + d[i + 1] ) % mod ; } } return res; } int main() { int kase = 0; while(~scanf("%s", s)) { init(); len = strlen(s); int n; scanf("%d", &n); for(int i = 0; i < n; i++) { scanf("%s", tmp); insert(tmp, 1); } d[len] = 1; for(int i = len - 1; i >= 0; i--) { d[i] = query(s, i); } printf("Case %d: %d\n", ++kase, d[0]); } return 0; }
相关文章推荐
- 《深入理解计算机系统》第一章计算机系统漫游笔记
- MyEclipse插件
- 替换字符串中的空格为其他字符
- 数据结构--栈的顺序存储
- 数据结构--归并排序
- JAVA IO-----字节流与字符流
- 数据结构(绪论)
- 数据结构学习---线性表
- Android开发之使用Get方法向服务器发送请求
- Android开发之HttpClient初步
- 消息机制中的问题
- Android开发之Handler(3)
- Android开发之Handler(2)
- Android开发之Handler
- Android 开发中的线程
- IOS开发之内存管理(2)
- IOS开发学习之内存管理
- [BZOJ1612][Usaco2008 Jan]Cow Contest奶牛的比赛 dfs
- 2016"百度之星" - 资格赛(Astar Round1)Problem A 线段树区间查询
- Hi