bzoj 4545 DQS 的 Trie
老年选手不会 SAM 也不会 LCT 系列
我的数据结构好菜啊 qnq
一颗 Trie 树,$q$ 次询问,每次可以是:
1.求这棵树上本质不同的子串数量
2.插入一个子树,保证总大小不超过 $100000$
3.询问一个字符串在 Trie 树上出现过多少次,保证所有询问串总长度不超过 $100000$
sol:
第一问显然就是个广义 SAM,可以在每次 extend 的时候顺便算出来
第二问和第三问要求动态维护 parent 树的子树 size,差分一下就变成了链加和单点查询,LCT 维护一下即可
注意的几个细节:
如果你要匹配一个整串,串在 SAM 上跑的时候是直接走 Trans 边,不跳 parent
(注意区别于,如果你要匹配一个串的子串,在 SAM 上跑的时候要跳 parent ,注意这两个不一样
LCT 的 link 和 cut,如果你使用的是不 makeroot 的偷懒写法,是不满足交换律的,一定都是一个方向(从上往下 link / cut)
为什么我不 makeroot 啊(平时啥都敢写系列
#include <bits/stdc++.h>
#define LL long long
#define rep(i, s, t) for (register int i = (s), i##end = (t); i <= i##end; ++i)
#define dwn(i, s, t) for (register int i = (s), i##end = (t); i >= i##end; --i)
using namespace std;
inline int read() {
int x = ,f = ; char ch = getchar();
for(; !isdigit(ch); ch = getchar())if(ch == '-') f = -f;
for(; isdigit(ch); ch = getchar())x = * x + ch - '';
return x * f;
}
const int maxn = ;
#define ls ch[x][0]
#define rs ch[x][1]
char s[maxn];
int n, node[maxn];
int ch[maxn][], fa[maxn], tag[maxn], val[maxn], st[maxn], top;
inline int isroot(int x) { return (ch[fa[x]][] != x) && (ch[fa[x]][] != x); }
inline void rotate(int x) {
int y = fa[x], z = fa[y];
int l = (ch[y][] == x), r = l ^ ;
if(!isroot(y)) ch[z][ch[z][] == y] = x;
fa[x] = z; fa[ch[x][r]] = y; fa[y] = x;
ch[y][l] = ch[x][r]; ch[x][r] = y;
}
inline void pushdown(int x) {
if(x && tag[x]) {
if(ls) tag[ls] += tag[x], val[ls] += tag[x];
if(rs) tag[rs] += tag[x], val[rs] += tag[x];
tag[x] = ;
}
}
inline void splay(int x) {
st[top = ] = x;
for(int i = x; !isroot(i); i = fa[i]) st[++top] = fa[i];
for(int i = top; i; i--) pushdown(st[i]);
while(!isroot(x)) {
int y = fa[x], z = fa[y];
if(!isroot(y)) {
if(ch[y][] == x ^ ch[z][] == y) rotate(x);
else rotate(y);
}
rotate(x);
}
}
inline void access(int x) {
for(int y = ; x; y = x, x = fa[x]) {
splay(x);
rs = y;
}
}
inline void link(int x, int y) {
fa[y] = x; //cerr << "link :" << x << " " << y << endl;
access(x); splay(x);
val[x] += val[y];
tag[x] += val[y];
}
inline void cut(int x, int y) {
access(y); splay(y); //cerr << "cut :" << x << " " << y << endl;
val[x] -= val[y];
tag[x] -= val[y];
fa[x] = ; ch[y][] = ;
}
int tr[maxn][], mxlen[maxn], pre[maxn], root, dfn;
LL ans;
int extend(int last, int c) {
int p = last, np = last = ++dfn;
mxlen[np] = mxlen[p] + ;
for(; p && !tr[p][c]; p = pre[p]) tr[p][c] = np;
if(!p) pre[np] = root, link(root, np);
else {
int q = tr[p][c];
if(mxlen[p] + == mxlen[q]) pre[np] = q, link(q, np);
else {
int nq = ++dfn;
mxlen[nq] = mxlen[p] + ;
pre[nq] = pre[q];
link(pre[q], nq);
memcpy(tr[nq], tr[q], sizeof(tr[nq]));
for(; p && tr[p][c] == q; p = pre[p]) tr[p][c] = nq;
cut(pre[q], q);
pre[np] = pre[q] = nq;
link(pre[q], q);link(pre[np], np);
}
}
ans += ((LL)mxlen[np] - (LL)mxlen[pre[np]]);
access(np); splay(np);
val[np]++; tag[np]++;
// cerr << np << endl;
return np;
}
int first[maxn], to[maxn << ], nx[maxn << ], va[maxn], cnt;
int vis[maxn], clo, par[maxn];
inline void add(int u, int v, int w) {
to[++cnt] = v;
va[cnt] = w;
nx[cnt] = first[u];
first[u] = cnt;
}
void dfs(int x) {
for(int i=first[x];i;i=nx[i]) {
if(to[i] == par[x] || vis[to[i]] != clo) continue;
par[to[i]] = x;
node[to[i]] = extend(node[x], va[i]);
dfs(to[i]);
}
}
int run() {
int now = root, len = strlen(s + );
rep(i, , len) {
// while(now && !tr[now][s[i] - 'a']) now = pre[now];
now = tr[now][s[i] - 'a'];
}
//cerr << now << endl;
if(!now) return ;
access(now); splay(now);
return val[now];
}
int main() {
//freopen("8.in","r",stdin);
//freopen("8oo.out","w",stdout);
//freopen("8oo_err","w",stderr);
root = ++dfn; node[] = root;
read(); n = read(); clo++;
rep(i, , n) {
int u = read(), v = read();
char ch; cin >> ch;
add(u, v, ch - 'a'); add(v, u, ch - 'a');
//cout << ch << endl;
vis[u] = vis[v] = clo;
} dfs();
int q = read();
while(q--) {
int opt = read();
if(opt == ) printf("%lld\n", ans);
else if(opt == ) {
int ri = read(), si = read(); clo++;
rep(i, , si) {
int u = read(), v = read();
char ch; cin >> ch;
add(u, v, ch - 'a'); add(v, u, ch - 'a');
vis[u] = vis[v] = clo;
} dfs(ri);
}
else if(opt == ) {
scanf("%s", s + );
printf("%d\n", run());
}
//int xo = 0;
// rep(i, 1, n) xo ^= node[i];
//cerr << xo << endl;
}
}
bzoj 4545 DQS 的 Trie的更多相关文章
- bzoj 4545: DQS的trie
Description DQS的自家阳台上种着一棵颗粒饱满.颜色纯正的trie. DQS的trie非常的奇特,它初始有n0个节点,n0-1条边,每条边上有一个字符.并且,它拥有极强的生长力:某个i时刻 ...
- BZOJ4545: DQS的trie
BZOJ4545: DQS的trie https://lydsy.com/JudgeOnline/problem.php?id=4545 分析: 对trie用dfs建sam复杂度是\(O(n^2)\) ...
- 【BZOJ4545】DQS的trie 后缀自动机+LCT
[BZOJ4545]DQS的trie Description DQS的自家阳台上种着一棵颗粒饱满.颜色纯正的trie. DQS的trie非常的奇特,它初始有n0个节点,n0-1条边,每条边上有一个字符 ...
- BZOJ 4545
bzoj 4545 给定一个踹树,支持几种操作. 本质不同子串询问 加入子树 询问字符串\(S\) 在树上的出现次数. 好码好码 重点就是维护\(parent\) 树,考虑用\(LCT\)维护此树. ...
- BZOJ 4260: Codechef REBXOR( trie )
求出前缀和, 那么以第x个元素结尾的最大异或值是max(sumx^sump)(1≤p<x), 用trie加速. 后缀同理, 然后扫一遍就OK了.时间复杂度O(31N) ------------- ...
- BZOJ 3689 异或 Trie木+堆
标题效果:特定n的数量,这种需求n数22 XOR的值前者k少 首先,我们建立了一个二进制的所有数字Trie木,您可以使用Trie木size域检查出一些其他的数字XOR值首先k少 然后,我们要保持一个堆 ...
- bzoj 2741 可持久化trie
首先我们设si为前i个数的xor和,那么对于询问区间[i,j]的xor和,就相当于si-1^sj,那么对于这道题的询问我们可以处理处si,然后对于询问[l,r],可以表示为在区间[l-1,r]里找两个 ...
- BZOJ - 3166 可持久化Trie 维护次大区间
题意:给出\(a[1...n]\),找出一个连续区间\(a[l...r],r>l\),令该区间的次大值为\(a_k\),使得\(a_k⊕a_i,l≤i≤r\)最大,输出全局最优解 (这题意有点别 ...
- bzoj 1819: 电子字典 Trie
题目: Description 人们在英文字典中查找某个单词的时候可能不知道该单词的完整拼法,而只知道该单词的一个错误的近似拼法,这时人们可能陷入困境,为了查找一个单词而浪费大量的时间.带有模糊查询功 ...
随机推荐
- Android LCD
Android LCD(一):LCD基本原理篇Android LCD(二):LCD常用接口原理篇Android LCD(三):Samsung LCD接口篇Android LCD(四):LCD驱动调试篇
- Python3:input()输入函数的用法
Python3:input()输入函数的用法 一.简介 input这个函数,第一个参数是提示语,它默认是空的.在我们使用input的时候,会从标准输入中读取一个string,即字符串(请注意,这里很重 ...
- 2018-2019-2 20165114《网络对抗技术》Exp4 恶意代码分析
Exp4 恶意代码分析 目录 一.实验目标 (1)监控你自己系统的运行状态,看有没有可疑的程序在运行. (2)分析一个恶意软件,就分析Exp2或Exp3中生成后门软件:分析工具尽量使用原生指令或sys ...
- 华为S5700系列交换机配置通过流策略实现VLAN间三层隔离
组网图形 图1 配置通过流策略实现VLAN间三层隔离组网图 组网需求 如图一所示,为了通信的安全性,某公司将访客.员工.服务器分别划分到VLAN10.VLAN20.VLAN30中.公司希望: 员工.服 ...
- jvm-知识点总结
参考: https://blog.csdn.net/wuqinghai2012/article/details/51485414 http://pengjiaheng.iteye.com/blog/5 ...
- LeetCode——Number of Boomerangs
LeetCode--Number of Boomerangs Question Given n points in the plane that are all pairwise distinct, ...
- LongestValidParentheses, 求最长合法括号子串长度-----同类问题ValidParentheses,GenerateParentheses
问题描述:求括号字符串中最长合法子串长度.例如:()((),返回2,而不是4. 算法分析:还是利用栈,和判断合法括号对是一样的. public static int longestValidParen ...
- javascript练习题·(1)
1.参数集合是什么? (function(){ return typeof arguments; })(); 的结果是? typeOf只能以字符串的形式返回数据类型 js中包括6种数据类型--Numb ...
- 地图Legend控件的使用
http://support.esrichina-bj.cn/2011/0318/1150.html
- Git GUI 的使用
下面,我们开始使用Git Gui 如果你想init一个本地的git仓库,到你的代码根目录下,右键选择Git Init Here 这时,你会发现在代码根目录下,生成了一个.git的隐藏属性目录. 再选择 ...