• (笔记整理未完成)【字符串算法:Trie树】


    基础知识  


    一 . 定义

    字典树(TrieTree),是一种树形结构,典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串,如01字典树)。字典树主要包含两种操作,插入查找,删除也可以完成,但是用得比较少。

    主要思想:利用字符串的公共前缀来节约存储空间。树中的来代表有无字符以及是哪个字符,每个节点存储的信息有是否为单词结尾以及后续字符是什么。很好地利用了串的公共前缀,节约了存储空间。

    Trie 树的核心思想是空间换时间。利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。


    模板题:洛谷 P8306 【模板】字典树

    题目描述

    给定 n 个模式串 s1​,s2​,…,sn​ 和 q 次询问,每次询问给定一个文本串 ti​,请回答s1​∼sn​ 中有多少个字符串 sj​ 满足 ti​ 是 sj​ 的前缀

    一个字符串 t 是 s 的前缀当且仅当从 s 的末尾删去若干个(可以为 0 个)连续的字符后与 t 相同。

    输入的字符串大小敏感。例如,字符串 Fusu 和字符串 fusu 不同。

    输入格式

    本题单测试点内有多组测试数据

    输入的第一行是一个整数,表示数据组数 T

    对于每组数据,格式如下:
    第一行是两个整数,分别表示模式串的个数 n 和询问的个数 q
    接下来 n 行,每行一个字符串,表示一个模式串。
    接下来 q 行,每行一个字符串,表示一次询问。

    输出格式

    按照输入的顺序依次输出各测试数据的答案。
    对于每次询问,输出一行一个整数表示答案。

    输入输出样例

    输入 #1

    3
    3 3
    fusufusu
    fusu
    anguei
    fusu
    anguei
    kkksc
    5 2
    fusu
    Fusu
    AFakeFusu
    afakefusu
    fusuisnotfake
    Fusu
    fusu
    1 1
    998244353
    9

    输出 #1

    2
    1
    0
    1
    2
    1

    说明/提示

    数据规模与约定

    对于全部的测试点,保证 1≤T,n,q≤10^5,且输入字符串的总长度不超过3× 10^6。输入的字符串只含大小写字母和数字,且不含空串。

    说明

    std 的 IO 使用的是关闭同步后的 cin/cout,本题不卡常。


    1. #include
    2. #include
    3. #include
    4. #include
    5. using namespace std;
    6. int cnt[3000005],trie[3000005][65];
    7. //一维数组cnt[N]用于存字符出现的次数
    8. //二维数组用于连接字典树的各个节点
    9. //二维数组的第二个位置需存‘A’~‘Z’,‘a’~‘z’,‘0’~‘9’共62个位点
    10. int T,idx,n,q;
    11. char s[3000005];
    12. int getnum(char x) //用于将字符转换成存入位置的序号
    13. {
    14. if('A'<=x&&x<='Z') return x-'A';
    15. else if('a'<=x &&x<='z')
    16. return x-'a'+26; //‘a’~‘z’存在‘A’~‘Z’往后的位置
    17. else return x-'0'+52;
    18. }
    19. void maketree(char s[])
    20. {
    21. int p=0,len=strlen(s); //p用于统计当前字符在树中的序号
    22. for(int i=0;i
    23. {
    24. int number=getnum(s[i]);
    25. if(trie[p][number]==0)
    26. trie[p][number]=++idx;
    27. p=trie[p][number];
    28. cnt[p]++;
    29. }
    30. }
    31. int search(char s[])
    32. {
    33. int p=0,len=strlen(s);
    34. for(int i=0;i
    35. {
    36. int number=getnum(s[i]);
    37. if(trie[p][number]==0) return 0;
    38. p=trie[p][number];
    39. }
    40. return cnt[p];
    41. }
    42. int main()
    43. {
    44. scanf("%d",&T);
    45. for(int k=1;k<=T;++k)
    46. {
    47. for(int i=0;i<=idx;++i)
    48. for(int j=0;j<=122;++j)
    49. trie[i][j]=0;
    50. for(int i=0;i<=idx;++i)
    51. cnt[i]=0;
    52. idx=0;
    53. //每次循环都是重新建字典树的过程,因此数组及指针需要清零
    54. cin>>n>>q;
    55. for(int i=1;i<=n;++i) //输入字符串构建字典树
    56. {
    57. scanf("%s",s);
    58. maketree(s);
    59. }
    60. for(int i=1;i<=q;++i) //在字典树中查找字符串
    61. {
    62. scanf("%s",s);
    63. printf("%d\n",search(s));
    64. }
    65. }
    66. return 0;
    67. }

    相关练习题:

    (待补充)1.洛谷 P1628 合并序列

     个人一开始的思路就是字典树,但是太菜了最后的查找与输出肝不出来QAQ 

     

     


    个人觉得讲得很好的课

  • 相关阅读:
    JAVA 版小程序商城免费搭建 多商家入驻 直播带货 商城系统 B2B2C 商城源码之 B2B2C产品概述
    什么是线上优雅停机和调整线程池参数?
    Vue再学习9——网络数据访问
    C#WPFPrism框架导航应用实例
    魅族MX4安装Ubuntu Touch 16.04
    恒容容器放气的瞬时流量的计算
    【Spring篇】Bean的三种配置和实例化方法
    Ubuntu 20.04 设置开机自启脚本
    46道面试题带你了解高级Java面试
    四、浏览器渲染过程,DOM,CSSDOM,渲染,布局,绘制详细介绍
  • 原文地址:https://blog.csdn.net/gzkeylucky/article/details/122631477