对于字典树和01字典树的一点理解:

首先,字典树建树的过程就是按照每个数的前缀来的,如果你要存储一个全小写字母字符串,那么这个树每一个节点最多26个节点,这样的话,如果要找特定的单词的话,按照建树的方式找就可以了。

然后是01字典树,这个树在处理一些异或问题的时候特别好用,首先在存储一个树的过程中,我们是按照从高位开始的,如果是对于int型的,我们就从这个数的32位开始存储,不够的话,按照0补,这是建树的过程。再就是查询的时候,对于给定的数,我们先去找这一位上和他不同的,比如说,如果当前这个数的第i位上是1,那我们就找有没有一个数第i位上是0,如果没有的话,再去找第i位是0的数,然后按照从高位到低位寻找的话,就一定能寻找到满足情况的最优解。

入门:

题目链接:http://acm.sdut.edu.cn/onlinejudge2/index.php/Home/Index/problemdetail/pid/2828.html

用数组模拟。

我的理解:假设给你n个字符串,我们可以把有相同前缀的按照树的形式存储下来,这样就能够节省很多的空间,然后通过递归的形式来建树或者查找子串是否存在或者存在的次数。

AC代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6+10;
char tmp[maxn];
int root[maxn][30];
int top;
void init()
{for(int i=0; i<top; i++){for(int j=0; j<30; j++){root[i][j]=0;}}top=0;
}
void add(char *str)
{int tot=0;int len=strlen(str);for(int i=0; i<len; i++){int t=str[i]-'a';if(root[tot][t]==0)root[tot][t]=++top;tot=root[tot][t];}
}
bool judge(char *str)
{int len=strlen(str);int tot=0;for(int i=0; i<len; i++){int t=str[i]-'a';if(root[tot][t]==0)return false;tot=root[tot][t];}return true;
}
int main()
{int n,m;top=0;while(~scanf("%d %d",&n,&m)&&(n+m)){init();for(int i=1; i<=n; i++){// getchar();scanf("%s",tmp);add(tmp);// cout<<tmp<<endl;}for(int i=1; i<=m; i++){//  getchar();scanf("%s",tmp);if(judge(tmp))printf("Yes\n");elseprintf("No\n");}}return 0;
}

A题:

题目链接:https://cn.vjudge.net/contest/276901#problem/A

题目大意:先输入若干个字符串,然后再每一次输入一个字符串,问你当前这个字符串再一开始输入的字符串中是前缀的有多少个?

AC代码:

#include<iostream>
#include<stack>
#include<string>
#include<cstring>
#include<stdio.h>
using namespace std;
# define ll long long
const int maxn = 2e6+100;
int rec[maxn][30];
int flag[maxn];
int tot;
char str1[maxn];
void add(char *str)
{int root=0;int len=strlen(str);for(int i=0; i<len; i++){int t=str[i]-'a';if(!rec[root][t])rec[root][t]=++tot;flag[rec[root][t]]++;root=rec[root][t];}
}
int judge(char *str)
{int root=0;int len=strlen(str);for(int i=0; i<len; i++){int t=str[i]-'a';if(rec[root][t]==0)return 0;root=rec[root][t];//cout<<i<<endl;}return flag[root];
}
void init()
{for(int i=0; i<tot; i++){for(int j=0; j<30; j++){rec[i][j]=0;}}tot=0;
}
int main()
{tot=0;while(gets(str1)){if(str1[0]=='\0') break;add(str1);}while(scanf("%s",str1)!=EOF){printf("%d\n",judge(str1));}return 0;
}// init();
//    while(gets(str1))
//    {
//        if(str1[0]=='\0')
//            break;
//        scanf("%s",str1);
//        add(str1);
//        getchar();
//    }
//    while(scanf("%s",str1)!=EOF)
//    {
//        int ans=judge(str1);
//        //cout<<str1<<endl;
//        printf("%d\n",ans);
//    }
//    return 0;
//}

B题:

分割字符串

版本一:使用函数 stringstream (头文件<sstream>)

https://blog.csdn.net/weixin_35929051/article/details/52502486?tdsourcetag=s_pcqq_aiomsg(stringstream的使用说明)

#include<iostream>
#include<stack>
#include<string>
#include<cstring>
#include<sstream>
#include<stdio.h>
using namespace std;
# define ll long long
const int maxn = 1e6+100;
int rec[maxn][30];
int flag[maxn];
int tot,ans;
string tmp,str1;
void add(string str)
{int root=0;int len=str.size();for(int i=0; i<len; i++){int t=str[i]-'a';if(!rec[root][t])rec[root][t]=++tot;root=rec[root][t];}if(flag[root]==0)ans++;flag[root]=1;
}
void init()
{// memset(flag,0,sizeof(flag));for(int i=0; i<=tot; i++){flag[i]=0;for(int j=0; j<30; j++){rec[i][j]=0;}}tot=0,ans=0;
}
int main()
{while(getline(cin,str1)){//cout<<str1<<endl;init();int p=0,t=0;if(str1=="#")break;stringstream ss(str1);while(ss>>str1){add(str1);}cout<<ans<<endl;// cout<<tot<<endl;}return 0;
}

版本二:(超时)

#include<iostream>
#include<stack>
#include<string>
#include<cstring>
#include<stdio.h>
using namespace std;
# define ll long long
const int maxn = 1e6+100;
int rec[maxn][30];
int flag[maxn];
int tot,ans;
char tmp[maxn],str1[maxn];
void add(char *str)
{int root=0;int len=strlen(str);for(int i=0; i<len; i++){int t=str[i]-'a';if(!rec[root][t])rec[root][t]=++tot;root=rec[root][t];}if(flag[root]==0)ans++;flag[root]=1;
}
void init()
{for(int i=0; i<=tot; i++){flag[i]=0;for(int j=0; j<30; j++){rec[i][j]=0;}}tot=0,ans=0;
}
int main()
{tot=0;while(gets(str1)){init();int p=0,t=0;if(str1[0]=='#')break;int len=strlen(str1);while(p<len){while(str1[p]!=' '&&p<len){tmp[t++]=str1[p];p++;}while(str1[p]==' '&&p<len)p++;add(tmp);t=0;}printf("%d\n",ans);getchar();}return 0;
}

01字典树:

首先输入n个数,然后每次输入一个数k,寻找输入的这个数和前面的n个数中的某一个最大的异或值?也就是k^s最大?

#include <iostream>
#include <string>
#include <deque>
#include <stack>
#include<cmath>
#include <algorithm>
#include<map>
using namespace std;
# define ll long long
# define inf 0x3f3f3f3f
const int maxn = 3e6+100;
ll flag[maxn];
int tot;
int sto[maxn][4];
void init()
{for(int i=0; i<=tot; i++){flag[i]=0;for(int j=0; j<3; j++){sto[i][j]=0;}}
}
void add(ll t)
{ll u=0;for(ll i=32; i>=0; i--){ll tmp=(t>>i)&1;if(sto[u][tmp]==0)sto[u][tmp]=++tot;u=sto[u][tmp];}flag[u]=t;
}
ll query(ll t)
{ll u=0;for(ll i=32; i>=0; i--){ll tmp=(t>>i)&1;if(sto[u][tmp^1])u=sto[u][tmp^1];elseu=sto[u][tmp];}return flag[u];
}
int main()
{int T;scanf("%d",&T);tot=0;int Case=0;while(T--){init();int n,m;scanf("%d %d",&n,&m);int tmp;for(int i=1; i<=n; i++){scanf("%d",&tmp);add(tmp);}printf("Case #%d:\n",++Case);for(int i=1; i<=m; i++){scanf("%d",&tmp);int ans=query(tmp);printf("%d\n",ans);}}return 0;
}

01字典树

HDU - 5536

具体思路:题目中说的是找三个不同的i,j,k,使得(a[i]+a[j])^a[k]的值最大,那么思路来了,首先第一步,我们先把所有的值全部存到字典树里面,然后两个for循环,每一次先把a[i]和a[j]去掉,然后再去求(a[i]+a[j])在字典树中的最值就可以了。

AC代码:

#include <iostream>
#include <string>
#include <deque>
#include <stack>
#include<cmath>
#include <algorithm>
#include<map>
using namespace std;
# define ll long long
# define inf 0x3f3f3f3f
# define ll_inf 1ll<<60
const int maxn = 1e6+100;
ll sto[maxn][3];
ll flag[maxn];
ll a[maxn],tot;
ll com[maxn];
ll Max(ll t1,ll t2)
{if(t1<t2)return t2;return t1;
}
void init()
{for(int i=0; i<=tot; i++){flag[i]=0;com[i]=0;for(int j=0; j<3; j++){sto[i][j]=0;}}tot=0;
}
void add(ll t)
{int u=0;for(int i=32; i>=0; i--){int tmp=(t>>i)&1;if(sto[u][tmp]==0)sto[u][tmp]=++tot;flag[sto[u][tmp]]++;u=sto[u][tmp];}com[u]=t;//存储这一位上是哪个数
}
void Erase(ll t)
{int u=0;for(int i=32; i>=0; i--){int tmp=(t>>i)&1;flag[sto[u][tmp]]--;//把这个数的路径走过的减去1,就相当于把这个数从树上去掉。u=sto[u][tmp];}// com[u]=0;
}
ll query(ll t)
{int u=0;for(int i=32; i>=0; i--){int tmp=(t>>i)&1;if(sto[u][tmp^1]>0)//看一下当前这一位上是不是有不一样的{if(flag[sto[u][tmp^1]]>0)//如果有,就按照不同进行u=sto[u][tmp^1];else// 没有的话,就按照另外一种来进行u=sto[u][tmp];}else{if(flag[sto[u][tmp]]>0)//同理u=sto[u][tmp];elseu=sto[u][tmp^1];}}return com[u]^t;
}
int main()
{int T;tot=0;scanf("%d",&T);while(T--){init();int n;scanf("%d",&n);for(int i=1; i<=n; i++){scanf("%lld",&a[i]);add(a[i]);}ll maxx=0;for(int i=1; i<=n; i++){Erase(a[i]);for(int j=i+1; j<=n; j++){Erase(a[j]);maxx=Max(maxx,query(a[i]+a[j]));add(a[j]);}add(a[i]);}printf("%lld\n",maxx);}return 0;
}

字典树01字典树专题对字典树的理解相关推荐

  1. 字典树-01字典树基础

    字典树-01字典树 什么是字典树? 字典树,又叫前缀树,Trie树,通常被用作字符串匹配. 它的实现原理是什么? 先建立一颗树,对于这棵树上每个节点i与其后继节点间的连线,都有存入一个字符. 对于存图 ...

  2. Educational Codeforces Round 23:E. Choosing The Commander(字典树01异或)

    Educational Codeforces Round 23:E. Choosing The Commander(字典树01异或) 题意: 3种操作: 1 插入一个数 2 删除一个数 3 给出一个数 ...

  3. 分门别类刷leetcode——高级数据结构(字典树,前缀树,trie树,并查集,线段树)

    目录 Trie树(字典树.前缀树)的基础知识 字典树的节点表示 字典树构造的例子 字典树的前序遍历 获取字典树中全部单词 字典树的整体功能 字典树的插入操作 字典树的搜索操作 字典树的前缀查询 字典树 ...

  4. python元组字典例子_python集合、元组、字典

    目录 主要内容: 集合 元组 字典 小总结 主要内容: 2.集合 3.元组 4.字典 复习: 字符串和元组一样,只能读不能写.列表和字典可以嵌套任何东西,列表可以嵌套列表 L = list(" ...

  5. c++中判断某个值在字典的value中_Python元组、字典、集合的简单介绍

    元组 Python的元组与列表类似,不同之处在于元组的元素不能修改. 元组使用小括号,列表使用方括号.元组和字符串都是是不可变序列. 语法:定义元组语法 () 和 , 访问元组:和列表一样:a[1] ...

  6. 字典怎么增加元素_python3基础之字典

    字典和列表一样,也是python内置的一种数据结构. 字典的结构如下图: 列表用中括号[]把元素包起来,而字典是用大括号{}把元素包起来,只不过字典的每一个元素都包含键和值两部分.键和值是一一对应的关 ...

  7. python定义一个字典并遍历字典中的键和值_python字典操作总结

    创建 方法一: 方法二:从Python 2.2 版本起,可以使用一个工厂方法,传入一个元素是列表的元组作为参数 方法三: 从Python 2.3 版本起, 可以用一个很方便的内建方法fromkeys( ...

  8. 如何根据字典中值的大小,对字典中的项排序

    如何根据字典中值的大小,对字典中的项排序 sorted(dict2.iteritems(),key=lambda item:item[1],reverse=True) 使用内置函数sorted  1. ...

  9. 课程及其编码字典python_【课程15】Python字典

    知识点1.字典(Dict)的定义 内置类型字典 注释:(元组).[列表].{字典} 1-键:-哈希类型---不可以改变的类型 1-整型.浮点.字符串(最多使用).元组---都可以是键的类型 2-不可以 ...

  10. 给定关键字不在字典中怎么解决_什么是字典?我们为什么要学它?你不知,现在你只需1分钟就可学会...

    Hello,大家好,在前面我们说过ExceL中间的数组使用方法,今天要给大家简单说下VBA字典的使用方法和优点.相信你看到具体的实例了,就会发现原来数组+字典这么厉害的.现在一起来看看吧! 那么有些同 ...

最新文章

  1. 如何格式化电脑_U盘提示格式化后如何恢复数据
  2. 单片机 c语言 按键长按短按,求助:单片机一键长按与短按按键实现的c程序有问题...
  3. 常见的数据结构——栈、队列、数组、链表和红黑树
  4. JFlow CCFlow工作流引擎北京培训邀请函
  5. 【BCH码2】BCH码的快速BM迭代译码原理详解及MATLAB实现(不使用MATLAB库函数-代码见CSDN同名资源)
  6. Effective Modern C++英文版及中文翻译
  7. 今日恐慌与贪婪指数为83 贪婪程度大幅上升
  8. 9-12 原生安装4
  9. 《货币战争》的一点感想
  10. mysql 主从 不一致_揭秘MySQL主从数据不一致
  11. 虚继承 - C++快速入门29
  12. java httppost raw_httpclient raw请求
  13. Python时间处理完全手册
  14. 单片机原理及应用程序c语言版题库,单片机原理及应用期末复习题库(含答案)...
  15. 一图读懂3GPP R16(附思维导图下载)
  16. Content Provider(二)之 FileProvider 实现应用文件共享
  17. iOS 8 界面设计 PSD 模板(iPhone 6),免费下载
  18. TMS570快速上手指南(0)--概述
  19. html video ajax,利用AJAX开源项目 在网页里播放视频实现方法
  20. 【算法❃思维与技巧】图解牛顿迭代法(力扣题实战)

热门文章

  1. 南非世界杯 小组赛 阿根廷vs尼日利亚
  2. 天网(绳子上的证据)
  3. 在屏幕上输出各种类型的数据
  4. 分页与分段的主要区别
  5. 五种网站跨域问题解决方案
  6. 0604课的预习任务 + 课堂笔记
  7. 谷歌趋势最好的代替品:Explodingtopics
  8. 注意力机制用于推荐系统问题(DIN,DIEN,BERT4Rec,PRM)
  9. 车型SUV、CRV和HRV、MPV是什么意思?
  10. 震惊!还能用Python制作微信红包封面,展现自己满满的诚意