题目:https://loj.ac/problem/6198

学习了学习了。

在sam上跑一个合并,将儿子节点的可用数字合并到parent树父亲节点,在01字典树上找异或最大值,再加上当前父亲节点表示的长度(lcp)来更新答案。
很简单明了的一个思路,但是有一个疑问,题目要求的是最长公共前缀,众所周知倒着建sam后树上两个节点的lcp就是其lca,那么这么一路向上合并,有很多时候我们走到的不是lca了,这种时候仿佛有不符合题意的嫌疑。

但是实际上,如果生成异或最大值的两个后缀在同一颗子树里,他们生成的答案在其lca位置是最大的,在之后的非lca位置生成的答案只会更小(parent树上表示的长度单调),不会影响到答案,而如果来自不同子树,当前的节点就是lca了。

#include<bits/stdc++.h>using namespace std;const int maxn = 1e5 + 5;int n, w[maxn];
char s[maxn];struct Trie {int next[maxn * 20][2], tot;int root[maxn << 1];void add(int &rt, int x) {rt = ++tot;int p = rt;for (int i = 16, c; i >= 0; --i) {c = (x >> i) & 1;if (!next[p][c]) {next[p][c] = ++tot;}p = next[p][c];}}int find(int p, int x) {int ans = 0;for (int i = 16, c; i >= 0; --i) {c = (x >> i) & 1;if (next[p][c ^ 1]) {p = next[p][c ^ 1], ans = ans << 1 | 1;} else {p = next[p][c], ans = ans << 1;}}return ans;}int merge(int x, int y) {if (!x || !y) {return x + y;}next[x][0] = merge(next[x][0], next[y][0]);next[x][1] = merge(next[x][1], next[y][1]);return x;}} trie;struct Sam {int next[maxn << 1][26];int link[maxn << 1], step[maxn << 1];vector<int> v[maxn << 1];int a[maxn], b[maxn << 1];int sz, last, root;void init() {//如多次建立自动机,加入memset操作root = sz = last = 1;}void add(int c) {int p = last;int np = ++sz;last = np;step[np] = step[p] + 1;while (!next[p][c] && p) {next[p][c] = np;p = link[p];}if (p == 0) {link[np] = root;} else {int q = next[p][c];if (step[p] + 1 == step[q]) {link[np] = q;} else {int nq = ++sz;memcpy(next[nq], next[q], sizeof(next[q]));step[nq] = step[p] + 1;link[nq] = link[q];link[q] = link[np] = nq;while (next[p][c] == q && p) {next[p][c] = nq;p = link[p];}}}}void build() {init();for (int i = n; i > 0; i--) {add(s[i] - 'a');v[last].push_back(w[i]);trie.add(trie.root[last], w[i]);}for (int i = 1; i <= sz; i++) {a[step[i]]++;}for (int i = 1; i <= step[last]; i++) {a[i] += a[i - 1];}for (int i = 1; i <= sz; i++) {b[a[step[i]]--] = i;}int ans = 0;for (int i = sz; i > root; --i) {int e = b[i];if (v[link[e]].size() < v[e].size()) {swap(trie.root[link[e]], trie.root[e]);swap(v[link[e]], v[e]);}int maxw = 0;for (auto j : v[e]) {v[link[e]].push_back(j);maxw = max(maxw, trie.find(trie.root[link[e]], j));}trie.root[link[e]] = trie.merge(trie.root[link[e]], trie.root[e]);ans = max(ans, step[link[e]] + maxw);}printf("%d\n", ans);}
} sam;int main() {scanf("%d%s", &n, s + 1);for (int i = 1; i <= n; ++i) {scanf("%d", &w[i]);}sam.build();return 0;
}

[LOJ6198] 谢特(sam+字典树合并)相关推荐

  1. CF1037H Security——SAM+线段树合并

    又是一道\(SAM\)维护\(endpos\)集合的题,我直接把CF700E的板子粘过来了QwQ 思路 如果我们有\([l,r]\)对应的\(SAM\),只需要在上面贪心就可以了.因为要求的是字典序比 ...

  2. P4770-[NOI2018]你的名字【SAM,线段树合并】

    正题 题目链接:https://www.luogu.com.cn/problem/P4770 题目大意 给出一个长度为nnn的字符串SSS.qqq次询问给出一个串TTT和一个区间[L,R][L,R][ ...

  3. CF700E-Cool Slogans【SAM,线段树合并,dp】

    正题 题目链接:https://www.luogu.com.cn/problem/CF700E 题目大意 给出一个字符串SSS,求一个最大的kkk使得存在kkk个字符串其中s1s_1s1​是SSS的子 ...

  4. 洛谷P4482 [BJWC2018]Border 的四种求法 字符串,SAM,线段树合并,线段树,树链剖分,DSU on Tree...

    原文链接https://www.cnblogs.com/zhouzhendong/p/LuoguP4482.html 题意 给定一个字符串 S,有 q 次询问,每次给定两个数 L,R ,求 S[L.. ...

  5. 2021CCPC华为云挑战赛:HDU 7091 重叠的子串(SAM + 线段树合并)

    重叠的子串 给定一个长度为n(1≤∣s∣≤105)n(1 \le \mid s \mid \le 10 ^ 5)n(1≤∣s∣≤105)的只由小写字母构成的字符串sss,有m,(1≤m≤106)m, ...

  6. CF666E-Forensic Examination【广义SAM,线段树合并】

    正题 题目链接:https://www.luogu.com.cn/problem/CF666E 解题思路 给出一个串SSS和nnn个串TiT_iTi​.mmm次询问Sa∼bS_{a\sim b}Sa∼ ...

  7. YbtOJ#532-往事之树【广义SAM,线段树合并】

    正题 题目链接:https://www.ybtoj.com.cn/problem/532 题目大意 给出nnn个点的一个TrieTrieTrie树,定义SxS_xSx​表示节点xxx代表的字符串 求m ...

  8. CF204E-Little Elephant and Strings【广义SAM,线段树合并】

    正题 题目链接:https://www.luogu.com.cn/problem/CF204E 题目大意 nnn个字符串的一个字符串集合,对于每个字符串求有多少个子串是这个字符串集合中至少kkk个字符 ...

  9. P4770:你的名字(SAM、线段树合并)

    文章目录 前言 解析 前言 1000A快乐!!!awa 没有想象中的那么恶心. 解析 先考虑每次都询问 [1,n][1,n][1,n] 如何做. 正难则反,用T所有本质不同串数量减去是S串子串又是T的 ...

  10. HDU 6191 2017广西邀请赛:Query on A Tree(字典树启发式合并)

    题意: 有一棵n个节点的树,每个节点都有一个值,m次查询,每次两个数x y表示以x为根的子树中哪个节点权值异或y得出的结果最大,求最大结果 离线 和线段树合并一样,在搜索过程中将多个字典树并在一起 每 ...

最新文章

  1. 【Zookeeper】Zookeeper集群“脑裂”问题处理大全
  2. 02.Apollo配置中心整合spring cloud zuul
  3. php 表单搜索,wordpress的搜索表单searchform.php
  4. PyCharm的高效使用技巧
  5. Servlet和JSP之间的区别
  6. 【antd】输入控件的思想
  7. mysql 清空表的两种方法
  8. 日语输入法电脑版_日语轻松入门小百科
  9. YSlow[转:大众点评]
  10. 去除QQ打/之后会出现的表情
  11. VBA代码执行过程中,显示程序的运行状态
  12. java+log4j+是异步吗_log4j2用asyncRoot配置异步日志是如何使用disruptor
  13. ADB Interface显示黄色惊叹号怎么办?
  14. 前端Unicode字符图标汇总
  15. 算法导论第八章练习参考答案
  16. arcgis拓扑几何,因缝隙太小而不能自动创建要素修复的处理办法
  17. 电脑怎么修改html5,详细教你怎么设置电脑默认浏览器
  18. 删除hive的分区元数据,spark总是读取到已经删掉的分区
  19. Springboot项目中使用Kafka
  20. js中当等于最小值是让代码不执行_28 个JavaScript编程黑科技,装逼指南,高逼格代码,让你惊叹不已...

热门文章

  1. P4238 【模板】多项式乘法逆
  2. 尝试校园网多拨速度叠加与复盘
  3. 以某SCI期刊为例说明该期刊投稿须知和流程
  4. vmware虚拟服务器数据备份,爱数VMware虚拟化平台备份恢复方案.pdf
  5. DT算法(暗像元法)在C6.1中的改进:Aerosol Dark Target (10km 3km) Collection 6.1 Changes
  6. 人生如逆旅,我亦是行人
  7. 我的世界服务器无限传送怎么办,我的世界:没有耐久,无限次使用“传送门”,比指令更实用...
  8. 黑苹果系统升级OC引导升级简单
  9. vue-$nextTick-等待页面渲染完毕的回调
  10. android 仿微信加载框,Android仿微信网络加载弹出框