• 835. Trie字符串统计,836。最大异或对,(Tire树,字典树)


    835. Trie字符串统计

    维护一个字符串集合,支持两种操作:

    1. I x 向集合中插入一个字符串 x
    1. Q x 询问一个字符串在集合中出现了多少次。

    共有 N

    个操作,输入的字符串总长度不超过 105

    ,字符串仅包含小写英文字母。

    输入格式

    第一行包含整数 N

    ,表示操作数。

    接下来 N

    行,每行包含一个操作指令,指令为 I xQ x 中的一种。

    输出格式

    对于每个询问指令 Q x,都要输出一个整数作为结果,表示 x

    在集合中出现的次数。

    每个结果占一行。

    数据范围

    1≤N≤2∗104

    输入样例:

    1. 5
    2. I abc
    3. Q abc
    4. Q ab
    5. I ab
    6. Q ab

    输出样例:

    1. 1
    2. 0
    3. 1

     

     * 由于字符串长度最多出现 1e5 个字符,所以一棵树最多有 1e5 层,又由于只有26个小写
     * 字母,那么每一个节点都需要预留 26 个子节点,因此开一个二维数组即可;
     *
     * 我们能保证每一个不同的前缀都处于不同的层;
     *
     * 但是我们又如何知道一个单词是否出现过,我们可以为每一个单词的尾字母所得到的儿子
     * 节点的值(它所处于的那一层的编号)(不同的单词的儿子节点的值一定是不相同的),
     * 作为 cnt 数组的下标,然后cnt[p]++ 表示以 这个单词结尾的个数得加一,同时又表示
     * 出了这是一个单词,而不是一个单词的前缀,处于前缀的单词此时还在for循环中探索字符
     * 的奥秘;(cnt 初始值等于0);

    1. /**
    2. * 由于字符串长度最多出现 1e5 个字符,所以一棵树最多有 1e5 层,又由于只有26个小写
    3. * 字母,那么每一个节点都需要预留 26 个子节点,因此开一个二维数组即可;
    4. *
    5. * 我们能保证每一个不同的前缀都处于不同的层;
    6. *
    7. * 但是我们又如何知道一个单词是否出现过,我们可以为每一个单词的尾字母所得到的儿子
    8. * 节点的值(它所处于的那一层的编号)(不同的单词的儿子节点的值一定是不相同的),
    9. * 作为 cnt 数组的下标,然后cnt[p]++ 表示以 这个单词结尾的个数得加一,同时又表示
    10. * 出了这是一个单词,而不是一个单词的前缀,处于前缀的单词此时还在for循环中探索字符
    11. * 的奥秘;(cnt 初始值等于0);
    12. */
    13. #include <iostream>
    14. #include <string>
    15. using namespace std;
    16. const int maxn = 1e5+10;
    17. int son[maxn][26],idx;
    18. int cnt[maxn];
    19. void insert(string s)
    20. {
    21. int p=0; //单词的首字母存在第0
    22. for(int i=0;i<s.size();++i)
    23. {
    24. int u=s[i]-'a';
    25. if(!son[p][u]) //如果这个单词没出现过,
    26. son[p][u]=++idx; //就将这个单词的这个字母存在son 数组的p行u列;
    27. p=son[p][u]; //继续探寻这个单词的下一个字母
    28. }
    29. ++cnt[p]; //p或者是之前出现过,或者是idx的值;但不管是哪一种情况,
    30. } //都能保证每个不同的单词最后得到的p值一定是独一无二的;
    31. int query(string s)
    32. {
    33. int p=0;
    34. for(int i=0;i<s.size();++i)
    35. {
    36. int u=s[i]-'a';
    37. if(!son[p][u]) //如果这个字母从来没出现过,那么这个单词必定没出现过,
    38. return 0; //直接返回0
    39. p=son[p][u];
    40. }
    41. return cnt[p]; //如果这个单词出现过,那么返回这个单词出现的次数;
    42. } //也有可能这个单词没出现过,但是是某个单词的前缀,也返回0
    43. int main()
    44. {
    45. int n;
    46. cin >> n;
    47. for(int i=0;i<n;++i)
    48. {
    49. string op,s;
    50. cin >> op >> s;
    51. if(op == "I")
    52. insert(s);
    53. else
    54. cout << query(s) << endl;
    55. }
    56. return 0;
    57. }

     

    143. 最大异或对

    在给定的 N

    个整数 A1,A2……AN 中选出两个进行 xor

    (异或)运算,得到的结果最大是多少?

    输入格式

    第一行输入一个整数 N

    第二行输入 N

    个整数 A1~AN

    输出格式

    输出一个整数表示答案。

    数据范围

    1≤N≤105

    ,
    0≤Ai<231

    输入样例:

    1. 3
    2. 1 2 3

    输出样例:

    3
    

     

     * 在n个数中选择两个数异或,当两个数的高位第一次不同时,此时的高位越高,那么这两个数
     * 的异或值就越大;
     *
     * 那么我们在选择 与x 的异或值最大的时候,我们必定选择其他数的二进制数的高位(第t位)
     * 与x的二进制数相同的高位(第t位)的二进制值(0,1)不同的数(y);
     * 那么我们把每一个数的二进制位存到字典树中,再查询与x异或值最大的值(这值就在这n个
     * 数的当中)是多少;
     * 把所有的数的异或值最大的数算出来,再进行比较,最后得到的最大的数就是答案;

    1. /**
    2. * 在n个数中选择两个数异或,当两个数的高位第一次不同时,此时的高位越高,那么这两个数
    3. * 的异或值就越大;
    4. *
    5. * 那么我们在选择 与x 的异或值最大的时候,我们必定选择其他数的二进制数的高位(第t位)
    6. * 与x的二进制数相同的高位(第t位)的二进制值(0,1)不同的数(y);
    7. * 那么我们把每一个数的二进制位存到字典树中,再查询与x异或值最大的值(这值就在这n个
    8. * 数的当中)是多少;
    9. * 把所有的数的异或值最大的数算出来,再进行比较,最后得到的最大的数就是答案;
    10. */
    11. #include <iostream>
    12. using namespace std;
    13. const int maxn = 1e5+10;
    14. int a[maxn];
    15. int son[maxn*31][2],idx;
    16. void insert(int v)
    17. {
    18. int p=0;
    19. for(int i=30;i>=0;--i)
    20. {
    21. int u=(v>>i) & 1;
    22. if(!son[p][u])
    23. son[p][u]=++idx;
    24. p=son[p][u];
    25. } //此题为什么没有cnt数组,因为每个数的二进制位数都是一样的,都是32位,
    26. } //最高位是符号位,就不进行运算了;
    27. int query(int x)
    28. {
    29. int p=0,res=0;
    30. for(int i=30;i>=0;--i)
    31. {
    32. int u=(x>>i) & 1; //求x的第i位的二进制数是多少;
    33. if(son[p][!u]) //如果u的兄弟节点存在(子节点最多存在两位)
    34. {
    35. p=son[p][!u];
    36. res=2*res+!u;
    37. }
    38. else
    39. {
    40. p=son[p][u];
    41. res=2*res+u;
    42. }
    43. }
    44. return res;
    45. }
    46. int main()
    47. {
    48. int n;
    49. cin >> n;
    50. for(int i=0;i<n;++i)
    51. {
    52. cin >> a[i];
    53. insert(a[i]);
    54. }
    55. int res =0;
    56. for(int i=0;i<n;++i)
    57. {
    58. int v=query(a[i]);
    59. res = max(res,a[i]^v);
    60. }
    61. cout << res << endl;
    62. return 0;
    63. }

  • 相关阅读:
    ADS原理图到Layout,Layout更新原理图
    element-ui plus 文件上传组件,设置单选,并支持替换和回显
    React-Redux实现组件间数据共享+项目打包
    专注效率提升「GitHub 热点速览 v.22.36」
    Vue引入Echarts图表的使用
    计算机毕业论文Java项目源码下载基于SSM的旅游资讯网站含前台与后台
    jni-02、lib路径、数组、对象、引用、extern修饰函数
    ERROR executor.CoarseGrainedExecutorBackend: RECEIVED SIGNAL TERM
    【C语言 模拟实现strncpy函数、strncat函数、strncmp函数、strstr函数】
    VSCode搭建内核源码阅读开发环境
  • 原文地址:https://blog.csdn.net/qq_51825761/article/details/126884290