对于字典树和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代码:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int maxn = 1e6+;
  4. char tmp[maxn];
  5. int root[maxn][];
  6. int top;
  7. void init()
  8. {
  9. for(int i=; i<top; i++)
  10. {
  11. for(int j=; j<; j++)
  12. {
  13. root[i][j]=;
  14. }
  15. }
  16. top=;
  17. }
  18. void add(char *str)
  19. {
  20. int tot=;
  21. int len=strlen(str);
  22. for(int i=; i<len; i++)
  23. {
  24. int t=str[i]-'a';
  25. if(root[tot][t]==)
  26. root[tot][t]=++top;
  27. tot=root[tot][t];
  28. }
  29. }
  30. bool judge(char *str)
  31. {
  32. int len=strlen(str);
  33. int tot=;
  34. for(int i=; i<len; i++)
  35. {
  36. int t=str[i]-'a';
  37. if(root[tot][t]==)
  38. return false;
  39. tot=root[tot][t];
  40. }
  41. return true;
  42. }
  43. int main()
  44. {
  45. int n,m;
  46. top=;
  47. while(~scanf("%d %d",&n,&m)&&(n+m))
  48. {
  49. init();
  50. for(int i=; i<=n; i++)
  51. {
  52. // getchar();
  53. scanf("%s",tmp);
  54. add(tmp);
  55. // cout<<tmp<<endl;
  56. }
  57. for(int i=; i<=m; i++)
  58. {
  59. // getchar();
  60. scanf("%s",tmp);
  61. if(judge(tmp))
  62. printf("Yes\n");
  63. else
  64. printf("No\n");
  65. }
  66. }
  67. return ;
  68. }

A题:

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

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

AC代码:

  1. #include<iostream>
  2. #include<stack>
  3. #include<string>
  4. #include<cstring>
  5. #include<stdio.h>
  6. using namespace std;
  7. # define ll long long
  8. const int maxn = 2e6+;
  9. int rec[maxn][];
  10. int flag[maxn];
  11. int tot;
  12. char str1[maxn];
  13. void add(char *str)
  14. {
  15. int root=;
  16. int len=strlen(str);
  17. for(int i=; i<len; i++)
  18. {
  19. int t=str[i]-'a';
  20. if(!rec[root][t])
  21. rec[root][t]=++tot;
  22. flag[rec[root][t]]++;
  23. root=rec[root][t];
  24.  
  25. }
  26. }
  27. int judge(char *str)
  28. {
  29. int root=;
  30. int len=strlen(str);
  31. for(int i=; i<len; i++)
  32. {
  33. int t=str[i]-'a';
  34. if(rec[root][t]==)
  35. return ;
  36. root=rec[root][t];
  37. //cout<<i<<endl;
  38. }
  39. return flag[root];
  40. }
  41. void init()
  42. {
  43. for(int i=; i<tot; i++)
  44. {
  45. for(int j=; j<; j++)
  46. {
  47. rec[i][j]=;
  48. }
  49. }
  50. tot=;
  51. }
  52. int main()
  53. {
  54. tot=;
  55. while(gets(str1))
  56. {
  57. if(str1[]=='\0') break;
  58. add(str1);
  59. }
  60. while(scanf("%s",str1)!=EOF)
  61. {
  62. printf("%d\n",judge(str1));
  63. }
  64. return ;
  65. }
  66. // init();
  67. // while(gets(str1))
  68. // {
  69. // if(str1[0]=='\0')
  70. // break;
  71. // scanf("%s",str1);
  72. // add(str1);
  73. // getchar();
  74. // }
  75. // while(scanf("%s",str1)!=EOF)
  76. // {
  77. // int ans=judge(str1);
  78. // //cout<<str1<<endl;
  79. // printf("%d\n",ans);
  80. // }
  81. // return 0;
  82. //}

B题:

分割字符串

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

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

  1. #include<iostream>
  2. #include<stack>
  3. #include<string>
  4. #include<cstring>
  5. #include<sstream>
  6. #include<stdio.h>
  7. using namespace std;
  8. # define ll long long
  9. const int maxn = 1e6+;
  10. int rec[maxn][];
  11. int flag[maxn];
  12. int tot,ans;
  13. string tmp,str1;
  14. void add(string str)
  15. {
  16. int root=;
  17. int len=str.size();
  18. for(int i=; i<len; i++)
  19. {
  20. int t=str[i]-'a';
  21. if(!rec[root][t])
  22. rec[root][t]=++tot;
  23. root=rec[root][t];
  24. }
  25. if(flag[root]==)
  26. ans++;
  27. flag[root]=;
  28. }
  29. void init()
  30. {
  31. // memset(flag,0,sizeof(flag));
  32. for(int i=; i<=tot; i++)
  33. {
  34. flag[i]=;
  35. for(int j=; j<; j++)
  36. {
  37. rec[i][j]=;
  38. }
  39. }
  40. tot=,ans=;
  41. }
  42. int main()
  43. {
  44. while(getline(cin,str1))
  45. {
  46. //cout<<str1<<endl;
  47. init();
  48. int p=,t=;
  49. if(str1=="#")
  50. break;
  51. stringstream ss(str1);
  52. while(ss>>str1)
  53. {
  54. add(str1);
  55. }
  56. cout<<ans<<endl;
  57. // cout<<tot<<endl;
  58. }
  59. return ;
  60. }

版本二:(超时)

  1. #include<iostream>
  2. #include<stack>
  3. #include<string>
  4. #include<cstring>
  5. #include<stdio.h>
  6. using namespace std;
  7. # define ll long long
  8. const int maxn = 1e6+;
  9. int rec[maxn][];
  10. int flag[maxn];
  11. int tot,ans;
  12. char tmp[maxn],str1[maxn];
  13. void add(char *str)
  14. {
  15. int root=;
  16. int len=strlen(str);
  17. for(int i=; i<len; i++)
  18. {
  19. int t=str[i]-'a';
  20. if(!rec[root][t])
  21. rec[root][t]=++tot;
  22. root=rec[root][t];
  23. }
  24. if(flag[root]==)ans++;
  25. flag[root]=;
  26. }
  27. void init()
  28. {
  29. for(int i=; i<=tot; i++)
  30. {
  31. flag[i]=;
  32. for(int j=; j<; j++)
  33. {
  34. rec[i][j]=;
  35. }
  36. }
  37. tot=,ans=;
  38. }
  39. int main()
  40. {
  41. tot=;
  42. while(gets(str1))
  43. {
  44. init();
  45. int p=,t=;
  46. if(str1[]=='#')
  47. break;
  48. int len=strlen(str1);
  49. while(p<len)
  50. {
  51. while(str1[p]!=' '&&p<len)
  52. {
  53. tmp[t++]=str1[p];
  54. p++;
  55. }
  56. while(str1[p]==' '&&p<len)
  57. p++;
  58. add(tmp);
  59. t=;
  60. }
  61. printf("%d\n",ans);
  62. getchar();
  63. }
  64. return ;
  65. }

01字典树:

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

  1. #include <iostream>
  2. #include <string>
  3. #include <deque>
  4. #include <stack>
  5. #include<cmath>
  6. #include <algorithm>
  7. #include<map>
  8. using namespace std;
  9. # define ll long long
  10. # define inf 0x3f3f3f3f
  11. const int maxn = 3e6+;
  12. ll flag[maxn];
  13. int tot;
  14. int sto[maxn][];
  15. void init()
  16. {
  17. for(int i=; i<=tot; i++)
  18. {
  19. flag[i]=;
  20. for(int j=; j<; j++)
  21. {
  22. sto[i][j]=;
  23. }
  24. }
  25. }
  26. void add(ll t)
  27. {
  28. ll u=;
  29. for(ll i=; i>=; i--)
  30. {
  31. ll tmp=(t>>i)&;
  32. if(sto[u][tmp]==)
  33. sto[u][tmp]=++tot;
  34. u=sto[u][tmp];
  35. }
  36. flag[u]=t;
  37. }
  38. ll query(ll t)
  39. {
  40. ll u=;
  41. for(ll i=; i>=; i--)
  42. {
  43. ll tmp=(t>>i)&;
  44. if(sto[u][tmp^])
  45. u=sto[u][tmp^];
  46. else
  47. u=sto[u][tmp];
  48. }
  49. return flag[u];
  50. }
  51. int main()
  52. {
  53. int T;
  54. scanf("%d",&T);
  55. tot=;
  56. int Case=;
  57. while(T--)
  58. {
  59. init();
  60. int n,m;
  61. scanf("%d %d",&n,&m);
  62. int tmp;
  63. for(int i=; i<=n; i++)
  64. {
  65. scanf("%d",&tmp);
  66. add(tmp);
  67. }
  68. printf("Case #%d:\n",++Case);
  69. for(int i=; i<=m; i++)
  70. {
  71. scanf("%d",&tmp);
  72. int ans=query(tmp);
  73. printf("%d\n",ans);
  74. }
  75. }
  76. return ;
  77. }

01字典树

HDU - 5536

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

AC代码:

  1. #include <iostream>
  2. #include <string>
  3. #include <deque>
  4. #include <stack>
  5. #include<cmath>
  6. #include <algorithm>
  7. #include<map>
  8. using namespace std;
  9. # define ll long long
  10. # define inf 0x3f3f3f3f
  11. # define ll_inf 1ll<<
  12. const int maxn = 1e6+;
  13. ll sto[maxn][];
  14. ll flag[maxn];
  15. ll a[maxn],tot;
  16. ll com[maxn];
  17. ll Max(ll t1,ll t2)
  18. {
  19. if(t1<t2)
  20. return t2;
  21. return t1;
  22. }
  23. void init()
  24. {
  25. for(int i=; i<=tot; i++)
  26. {
  27. flag[i]=;
  28. com[i]=;
  29. for(int j=; j<; j++)
  30. {
  31. sto[i][j]=;
  32. }
  33. }
  34. tot=;
  35. }
  36. void add(ll t)
  37. {
  38. int u=;
  39. for(int i=; i>=; i--)
  40. {
  41. int tmp=(t>>i)&;
  42. if(sto[u][tmp]==)
  43. sto[u][tmp]=++tot;
  44. flag[sto[u][tmp]]++;
  45. u=sto[u][tmp];
  46. }
  47. com[u]=t;//存储这一位上是哪个数
  48. }
  49. void Erase(ll t)
  50. {
  51. int u=;
  52. for(int i=; i>=; i--)
  53. {
  54. int tmp=(t>>i)&;
  55. flag[sto[u][tmp]]--;//把这个数的路径走过的减去1,就相当于把这个数从树上去掉。
  56. u=sto[u][tmp];
  57. }
  58. // com[u]=0;
  59. }
  60. ll query(ll t)
  61. {
  62. int u=;
  63. for(int i=; i>=; i--)
  64. {
  65. int tmp=(t>>i)&;
  66. if(sto[u][tmp^]>)//看一下当前这一位上是不是有不一样的
  67. {
  68. if(flag[sto[u][tmp^]]>)//如果有,就按照不同进行
  69. u=sto[u][tmp^];
  70. else// 没有的话,就按照另外一种来进行
  71. u=sto[u][tmp];
  72. }
  73. else
  74. {
  75. if(flag[sto[u][tmp]]>)//同理
  76. u=sto[u][tmp];
  77. else
  78. u=sto[u][tmp^];
  79. }
  80. }
  81. return com[u]^t;
  82. }
  83. int main()
  84. {
  85. int T;
  86. tot=;
  87. scanf("%d",&T);
  88. while(T--)
  89. {
  90. init();
  91. int n;
  92. scanf("%d",&n);
  93. for(int i=; i<=n; i++)
  94. {
  95. scanf("%lld",&a[i]);
  96. add(a[i]);
  97. }
  98. ll maxx=;
  99. for(int i=; i<=n; i++)
  100. {
  101. Erase(a[i]);
  102. for(int j=i+; j<=n; j++)
  103. {
  104. Erase(a[j]);
  105. maxx=Max(maxx,query(a[i]+a[j]));
  106. add(a[j]);
  107. }
  108. add(a[i]);
  109. }
  110. printf("%lld\n",maxx);
  111. }
  112. return ;
  113. }

字典树&&01字典树专题&&对字典树的理解的更多相关文章

  1. 字典树基础进阶全掌握(Trie树、01字典树、后缀自动机、AC自动机)

    字典树 概述     字典树,又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种.典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计.它 ...

  2. Leedcode算法专题训练(树)

    递归 一棵树要么是空树,要么有两个指针,每个指针指向一棵树.树是一种递归结构,很多树的问题可以使用递归来处理. 1. 树的高度 104. Maximum Depth of Binary Tree (E ...

  3. python-Day3-set 集合-counter计数器-默认字典(defaultdict) -可命名元组(namedtuple)-有序字典(orderedDict)-双向队列(deque)--Queue单项队列--深浅拷贝---函数参数

    上节内容回顾:C语言为什么比起他语言块,因为C 会把代码变异成机器码Pyhton 的 .pyc文件是什么python 把.py文件编译成的.pyc文件是Python的字节码, 字符串本质是 字符数组, ...

  4. 总结day5 ---- ,字典的学习,增删改查,以及字典的嵌套, 赋值运算

    内容大纲: 一:字典的定义 二:字典的增加 >1:按照key增加,  无则增加,有则覆盖 >2:setdefault()  ,无则增加,有则不变 三:字典的删除 >1:pop()  ...

  5. Leetcode之深度优先搜索(DFS)专题-513. 找树左下角的值(Find Bottom Left Tree Value)

    Leetcode之深度优先搜索(DFS)专题-513. 找树左下角的值(Find Bottom Left Tree Value) 深度优先搜索的解题详细介绍,点击 给定一个二叉树,在树的最后一行找到最 ...

  6. LeetCode初级算法--树01:二叉树的最大深度

    LeetCode初级算法--树01:二叉树的最大深度 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.n ...

  7. 1、如何在列表,字典,集合种根据条件筛选数据?2、如何为元组中的每个元素命名,提高程序的可读性3、如何统计出序列中元素出现的频度4、如何根据字典中value的大小,对字典的key进行排序

    一.数据筛选: 处理方式: 1.filter函数在py3,返回的是个生成式. from random import randint data = [randint(-100,100) for i in ...

  8. Python字典列表字段重组形成新的字典

    最近遇到这样一个需求,需要将字典列表中的字段进行重组,形成一个新的字典.举个例子吧: l1 = [{"x": 22, "y": 22, "demand ...

  9. C#3.0新增功能10 表达式树 01 简介

    连载目录    [已更新最新开发文章,点击查看详细] 如果你使用过 LINQ,则会有丰富库(其中 Func 类型是 API 集的一部分)的经验. (如果尚不熟悉 LINQ,建议阅读 LINQ 教程,以 ...

  10. zoj2112 主席树动态第k大 (主席树&&树状数组)

    Dynamic Rankings Time Limit: 10 Seconds      Memory Limit: 32768 KB The Company Dynamic Rankings has ...

随机推荐

  1. AtCoder Grand Contest 029 翻车记

    A:对于每个B,会和其右边的每个W交换一次. #include<iostream> #include<cstdio> #include<cmath> #includ ...

  2. MT【114】构造二次函数

    评:b+c,bc好比向量里的一组基底,可以将关于b,c的对称式表示出来.

  3. pragma指令详解(转载)

    #pragma comment( comment-type [,"commentstring"] ) 该宏放置一个注释到对象文件或者可执行文件.comment-type是一个预定义 ...

  4. Markdown中添加数学公式

    平时写技术博客的时候数学公式还是用的挺多的,之前一直都是在本地写完数学公式之后做成图片添加到博客中,但是这样很不方便.所以现在介绍一种在Markdown中添加数学公式的方法. 使用MathJax引擎 ...

  5. kafka问题集(一):broker少于kafka节点数

    问题集仅为个人实践,若有不准确的,欢迎交流! 一.现象: 集群有3台kafka服务器,而kafka 的9002界面上broker仅有2个:log.dirs配置路径为/data/kafka/data,而 ...

  6. java插件之Lombok

    使用注释来减少Java中的重复代码 @NonNull - 或者:我怎么学会停止担心和喜欢上了NullPointerException. @Cleanup - 自动资源管理:安全地调用您的close() ...

  7. C++ 实现vector<std:string> 版本

    #include <iostream> #include <vector> #include <memory> #include <thread> #i ...

  8. Nginx Upstream Keepalive 分析 保持长连接

    Nginx Upstream长连接由upstream模式下的keepalive指令控制,并指定可用于长连接的连接数,配置样例如下: upstream http_backend {     server ...

  9. linux命令总结之seq命令

    功能: seq命令用于产生从某个数到另外一个数之间的所有整数. 语法: seq [选项]... 尾数 seq [选项]... 首数 尾数 seq [选项]... 首数 增量 尾数 选项: -f, -- ...

  10. Python【yagmail】模块发邮件

    #步骤一:import yagmail #步骤二:实例化一个发邮件的对象username = '553637138@qq.com' #邮箱账号pwd='sa2008' #授权码mail = yagma ...