字典树&&01字典树专题&&对字典树的理解
对于字典树和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+;
- char tmp[maxn];
- int root[maxn][];
- int top;
- void init()
- {
- for(int i=; i<top; i++)
- {
- for(int j=; j<; j++)
- {
- root[i][j]=;
- }
- }
- top=;
- }
- void add(char *str)
- {
- int tot=;
- int len=strlen(str);
- for(int i=; i<len; i++)
- {
- int t=str[i]-'a';
- if(root[tot][t]==)
- root[tot][t]=++top;
- tot=root[tot][t];
- }
- }
- bool judge(char *str)
- {
- int len=strlen(str);
- int tot=;
- for(int i=; i<len; i++)
- {
- int t=str[i]-'a';
- if(root[tot][t]==)
- return false;
- tot=root[tot][t];
- }
- return true;
- }
- int main()
- {
- int n,m;
- top=;
- while(~scanf("%d %d",&n,&m)&&(n+m))
- {
- init();
- for(int i=; i<=n; i++)
- {
- // getchar();
- scanf("%s",tmp);
- add(tmp);
- // cout<<tmp<<endl;
- }
- for(int i=; i<=m; i++)
- {
- // getchar();
- scanf("%s",tmp);
- if(judge(tmp))
- printf("Yes\n");
- else
- printf("No\n");
- }
- }
- return ;
- }
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+;
- int rec[maxn][];
- int flag[maxn];
- int tot;
- char str1[maxn];
- void add(char *str)
- {
- int root=;
- int len=strlen(str);
- for(int i=; 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=;
- int len=strlen(str);
- for(int i=; i<len; i++)
- {
- int t=str[i]-'a';
- if(rec[root][t]==)
- return ;
- root=rec[root][t];
- //cout<<i<<endl;
- }
- return flag[root];
- }
- void init()
- {
- for(int i=; i<tot; i++)
- {
- for(int j=; j<; j++)
- {
- rec[i][j]=;
- }
- }
- tot=;
- }
- int main()
- {
- tot=;
- while(gets(str1))
- {
- if(str1[]=='\0') break;
- add(str1);
- }
- while(scanf("%s",str1)!=EOF)
- {
- printf("%d\n",judge(str1));
- }
- return ;
- }
- // 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+;
- int rec[maxn][];
- int flag[maxn];
- int tot,ans;
- string tmp,str1;
- void add(string str)
- {
- int root=;
- int len=str.size();
- for(int i=; i<len; i++)
- {
- int t=str[i]-'a';
- if(!rec[root][t])
- rec[root][t]=++tot;
- root=rec[root][t];
- }
- if(flag[root]==)
- ans++;
- flag[root]=;
- }
- void init()
- {
- // memset(flag,0,sizeof(flag));
- for(int i=; i<=tot; i++)
- {
- flag[i]=;
- for(int j=; j<; j++)
- {
- rec[i][j]=;
- }
- }
- tot=,ans=;
- }
- int main()
- {
- while(getline(cin,str1))
- {
- //cout<<str1<<endl;
- init();
- int p=,t=;
- if(str1=="#")
- break;
- stringstream ss(str1);
- while(ss>>str1)
- {
- add(str1);
- }
- cout<<ans<<endl;
- // cout<<tot<<endl;
- }
- return ;
- }
版本二:(超时)
- #include<iostream>
- #include<stack>
- #include<string>
- #include<cstring>
- #include<stdio.h>
- using namespace std;
- # define ll long long
- const int maxn = 1e6+;
- int rec[maxn][];
- int flag[maxn];
- int tot,ans;
- char tmp[maxn],str1[maxn];
- void add(char *str)
- {
- int root=;
- int len=strlen(str);
- for(int i=; i<len; i++)
- {
- int t=str[i]-'a';
- if(!rec[root][t])
- rec[root][t]=++tot;
- root=rec[root][t];
- }
- if(flag[root]==)ans++;
- flag[root]=;
- }
- void init()
- {
- for(int i=; i<=tot; i++)
- {
- flag[i]=;
- for(int j=; j<; j++)
- {
- rec[i][j]=;
- }
- }
- tot=,ans=;
- }
- int main()
- {
- tot=;
- while(gets(str1))
- {
- init();
- int p=,t=;
- if(str1[]=='#')
- 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=;
- }
- printf("%d\n",ans);
- getchar();
- }
- return ;
- }
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+;
- ll flag[maxn];
- int tot;
- int sto[maxn][];
- void init()
- {
- for(int i=; i<=tot; i++)
- {
- flag[i]=;
- for(int j=; j<; j++)
- {
- sto[i][j]=;
- }
- }
- }
- void add(ll t)
- {
- ll u=;
- for(ll i=; i>=; i--)
- {
- ll tmp=(t>>i)&;
- if(sto[u][tmp]==)
- sto[u][tmp]=++tot;
- u=sto[u][tmp];
- }
- flag[u]=t;
- }
- ll query(ll t)
- {
- ll u=;
- for(ll i=; i>=; i--)
- {
- ll tmp=(t>>i)&;
- if(sto[u][tmp^])
- u=sto[u][tmp^];
- else
- u=sto[u][tmp];
- }
- return flag[u];
- }
- int main()
- {
- int T;
- scanf("%d",&T);
- tot=;
- int Case=;
- while(T--)
- {
- init();
- int n,m;
- scanf("%d %d",&n,&m);
- int tmp;
- for(int i=; i<=n; i++)
- {
- scanf("%d",&tmp);
- add(tmp);
- }
- printf("Case #%d:\n",++Case);
- for(int i=; i<=m; i++)
- {
- scanf("%d",&tmp);
- int ans=query(tmp);
- printf("%d\n",ans);
- }
- }
- return ;
- }
01字典树
具体思路:题目中说的是找三个不同的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<<
- const int maxn = 1e6+;
- ll sto[maxn][];
- 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=; i<=tot; i++)
- {
- flag[i]=;
- com[i]=;
- for(int j=; j<; j++)
- {
- sto[i][j]=;
- }
- }
- tot=;
- }
- void add(ll t)
- {
- int u=;
- for(int i=; i>=; i--)
- {
- int tmp=(t>>i)&;
- if(sto[u][tmp]==)
- sto[u][tmp]=++tot;
- flag[sto[u][tmp]]++;
- u=sto[u][tmp];
- }
- com[u]=t;//存储这一位上是哪个数
- }
- void Erase(ll t)
- {
- int u=;
- for(int i=; i>=; i--)
- {
- int tmp=(t>>i)&;
- flag[sto[u][tmp]]--;//把这个数的路径走过的减去1,就相当于把这个数从树上去掉。
- u=sto[u][tmp];
- }
- // com[u]=0;
- }
- ll query(ll t)
- {
- int u=;
- for(int i=; i>=; i--)
- {
- int tmp=(t>>i)&;
- if(sto[u][tmp^]>)//看一下当前这一位上是不是有不一样的
- {
- if(flag[sto[u][tmp^]]>)//如果有,就按照不同进行
- u=sto[u][tmp^];
- else// 没有的话,就按照另外一种来进行
- u=sto[u][tmp];
- }
- else
- {
- if(flag[sto[u][tmp]]>)//同理
- u=sto[u][tmp];
- else
- u=sto[u][tmp^];
- }
- }
- return com[u]^t;
- }
- int main()
- {
- int T;
- tot=;
- scanf("%d",&T);
- while(T--)
- {
- init();
- int n;
- scanf("%d",&n);
- for(int i=; i<=n; i++)
- {
- scanf("%lld",&a[i]);
- add(a[i]);
- }
- ll maxx=;
- for(int i=; i<=n; i++)
- {
- Erase(a[i]);
- for(int j=i+; 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 ;
- }
字典树&&01字典树专题&&对字典树的理解的更多相关文章
- 字典树基础进阶全掌握(Trie树、01字典树、后缀自动机、AC自动机)
字典树 概述 字典树,又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种.典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计.它 ...
- Leedcode算法专题训练(树)
递归 一棵树要么是空树,要么有两个指针,每个指针指向一棵树.树是一种递归结构,很多树的问题可以使用递归来处理. 1. 树的高度 104. Maximum Depth of Binary Tree (E ...
- python-Day3-set 集合-counter计数器-默认字典(defaultdict) -可命名元组(namedtuple)-有序字典(orderedDict)-双向队列(deque)--Queue单项队列--深浅拷贝---函数参数
上节内容回顾:C语言为什么比起他语言块,因为C 会把代码变异成机器码Pyhton 的 .pyc文件是什么python 把.py文件编译成的.pyc文件是Python的字节码, 字符串本质是 字符数组, ...
- 总结day5 ---- ,字典的学习,增删改查,以及字典的嵌套, 赋值运算
内容大纲: 一:字典的定义 二:字典的增加 >1:按照key增加, 无则增加,有则覆盖 >2:setdefault() ,无则增加,有则不变 三:字典的删除 >1:pop() ...
- Leetcode之深度优先搜索(DFS)专题-513. 找树左下角的值(Find Bottom Left Tree Value)
Leetcode之深度优先搜索(DFS)专题-513. 找树左下角的值(Find Bottom Left Tree Value) 深度优先搜索的解题详细介绍,点击 给定一个二叉树,在树的最后一行找到最 ...
- LeetCode初级算法--树01:二叉树的最大深度
LeetCode初级算法--树01:二叉树的最大深度 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.n ...
- 1、如何在列表,字典,集合种根据条件筛选数据?2、如何为元组中的每个元素命名,提高程序的可读性3、如何统计出序列中元素出现的频度4、如何根据字典中value的大小,对字典的key进行排序
一.数据筛选: 处理方式: 1.filter函数在py3,返回的是个生成式. from random import randint data = [randint(-100,100) for i in ...
- Python字典列表字段重组形成新的字典
最近遇到这样一个需求,需要将字典列表中的字段进行重组,形成一个新的字典.举个例子吧: l1 = [{"x": 22, "y": 22, "demand ...
- C#3.0新增功能10 表达式树 01 简介
连载目录 [已更新最新开发文章,点击查看详细] 如果你使用过 LINQ,则会有丰富库(其中 Func 类型是 API 集的一部分)的经验. (如果尚不熟悉 LINQ,建议阅读 LINQ 教程,以 ...
- zoj2112 主席树动态第k大 (主席树&&树状数组)
Dynamic Rankings Time Limit: 10 Seconds Memory Limit: 32768 KB The Company Dynamic Rankings has ...
随机推荐
- AtCoder Grand Contest 029 翻车记
A:对于每个B,会和其右边的每个W交换一次. #include<iostream> #include<cstdio> #include<cmath> #includ ...
- MT【114】构造二次函数
评:b+c,bc好比向量里的一组基底,可以将关于b,c的对称式表示出来.
- pragma指令详解(转载)
#pragma comment( comment-type [,"commentstring"] ) 该宏放置一个注释到对象文件或者可执行文件.comment-type是一个预定义 ...
- Markdown中添加数学公式
平时写技术博客的时候数学公式还是用的挺多的,之前一直都是在本地写完数学公式之后做成图片添加到博客中,但是这样很不方便.所以现在介绍一种在Markdown中添加数学公式的方法. 使用MathJax引擎 ...
- kafka问题集(一):broker少于kafka节点数
问题集仅为个人实践,若有不准确的,欢迎交流! 一.现象: 集群有3台kafka服务器,而kafka 的9002界面上broker仅有2个:log.dirs配置路径为/data/kafka/data,而 ...
- java插件之Lombok
使用注释来减少Java中的重复代码 @NonNull - 或者:我怎么学会停止担心和喜欢上了NullPointerException. @Cleanup - 自动资源管理:安全地调用您的close() ...
- C++ 实现vector<std:string> 版本
#include <iostream> #include <vector> #include <memory> #include <thread> #i ...
- Nginx Upstream Keepalive 分析 保持长连接
Nginx Upstream长连接由upstream模式下的keepalive指令控制,并指定可用于长连接的连接数,配置样例如下: upstream http_backend { server ...
- linux命令总结之seq命令
功能: seq命令用于产生从某个数到另外一个数之间的所有整数. 语法: seq [选项]... 尾数 seq [选项]... 首数 尾数 seq [选项]... 首数 增量 尾数 选项: -f, -- ...
- Python【yagmail】模块发邮件
#步骤一:import yagmail #步骤二:实例化一个发邮件的对象username = '553637138@qq.com' #邮箱账号pwd='sa2008' #授权码mail = yagma ...