trie 树
基本操作
顾名思义,\(trie\) 树就像字典一样,是一种多串状态的集合表现
处理字母
处理字母的关键在于每个串结束处的处理,常见的有开 \(vector\),节点上的 \(dp\)(虽然可能更多的是在 \(AC\) 自动机上)
考虑 \(trie\) 树上的 \(dp\),\(f[i][j]\) 表示走到节点 \(i\),匹配到模式串 \(j\) 可不可行
模式串如果为字母,直接进对应儿子
如果为 \(?\),进所有儿子
如果为 \(*\),进所有儿子且模式串不延伸,或只模式串延伸
一个比较神奇的套路,对于字符的大小关系,体现于建图
首先枚举假定哪个串是最小的,然后字典树跟着扫一遍,可以对应出许多大小关系,然后建出有向图,跑一遍拓扑判环即可,或许比较像差分约束?
第一次见随机数据干这用……
由于数据随机,\(lcp\) 较短,只存后缀前 \(40\) 个即可
考虑计算,对于每一个右端点,记录所有长度的 \(lcp\) 最右左端点,暴力跳即可
处理数字
按位建立 \(01\) \(trie\) 树,甚至可以很大程度上代替平衡树(除了区间翻转)
一般套路是让求最大异或,往相反的儿子走即可
一个经典套路是如果求区间异或和,转化为前缀和的单点匹配
先求前缀和,由于前后不好区分,那么以点对考虑,即先把限制乘 \(2\),然后重复计算
一个很妙的方法是由于单调性,所以把每个点的最大价值放进堆里,每次求的第 \(k\) 的 \(k\) 加 \(1\) 即可
重点来实现全局加一操作
考虑一个数加一的本质,为最后若干个变零,第一个零变1
那么我们从低位到高位建立 \(trie\) 树,那么全局加一操作变为交换左右子树,并对零子树继续这个操作
一些坑点:
- 一定要把 \(tot\) 初值设为 \(1\)
- 01 要从高位开始,左移 \(1ll\),用 \(bool\) 保存或者改成右移
- 一个关键点的贡献算完后考虑是否清空