老年选手不会 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的更多相关文章

  1. bzoj 4545: DQS的trie

    Description DQS的自家阳台上种着一棵颗粒饱满.颜色纯正的trie. DQS的trie非常的奇特,它初始有n0个节点,n0-1条边,每条边上有一个字符.并且,它拥有极强的生长力:某个i时刻 ...

  2. BZOJ4545: DQS的trie

    BZOJ4545: DQS的trie https://lydsy.com/JudgeOnline/problem.php?id=4545 分析: 对trie用dfs建sam复杂度是\(O(n^2)\) ...

  3. 【BZOJ4545】DQS的trie 后缀自动机+LCT

    [BZOJ4545]DQS的trie Description DQS的自家阳台上种着一棵颗粒饱满.颜色纯正的trie. DQS的trie非常的奇特,它初始有n0个节点,n0-1条边,每条边上有一个字符 ...

  4. BZOJ 4545

    bzoj 4545 给定一个踹树,支持几种操作. 本质不同子串询问 加入子树 询问字符串\(S\) 在树上的出现次数. 好码好码 重点就是维护\(parent\) 树,考虑用\(LCT\)维护此树. ...

  5. BZOJ 4260: Codechef REBXOR( trie )

    求出前缀和, 那么以第x个元素结尾的最大异或值是max(sumx^sump)(1≤p<x), 用trie加速. 后缀同理, 然后扫一遍就OK了.时间复杂度O(31N) ------------- ...

  6. BZOJ 3689 异或 Trie木+堆

    标题效果:特定n的数量,这种需求n数22 XOR的值前者k少 首先,我们建立了一个二进制的所有数字Trie木,您可以使用Trie木size域检查出一些其他的数字XOR值首先k少 然后,我们要保持一个堆 ...

  7. bzoj 2741 可持久化trie

    首先我们设si为前i个数的xor和,那么对于询问区间[i,j]的xor和,就相当于si-1^sj,那么对于这道题的询问我们可以处理处si,然后对于询问[l,r],可以表示为在区间[l-1,r]里找两个 ...

  8. BZOJ - 3166 可持久化Trie 维护次大区间

    题意:给出\(a[1...n]\),找出一个连续区间\(a[l...r],r>l\),令该区间的次大值为\(a_k\),使得\(a_k⊕a_i,l≤i≤r\)最大,输出全局最优解 (这题意有点别 ...

  9. bzoj 1819: 电子字典 Trie

    题目: Description 人们在英文字典中查找某个单词的时候可能不知道该单词的完整拼法,而只知道该单词的一个错误的近似拼法,这时人们可能陷入困境,为了查找一个单词而浪费大量的时间.带有模糊查询功 ...

随机推荐

  1. redis 学习笔记(二)

    1. 在centos下安装g++,如果输入 yum install g++,那么将会提示找不到g++.因为在centos下g++安装包名字叫做:gcc-c++ 所以应该输入 yum install g ...

  2. powerdesigner解决创建多个表表主键名称重复的问题

    选择菜单栏的tools选项,选择Model  Options..,选择Model Settings  只要将图片中的选择打钩去掉即可(操作步骤1),同时设置为默认选项(操作步骤2),防止以后问题又出现 ...

  3. 多种数据库之间 update的不同

    sql server update a set a.gqdltks=b.gqdltks,a.bztks=b.bztks from landleveldata a,gdqlpj b where a.GE ...

  4. StringUtils用法(isNotEmpty和isNotBlank)

    isNotEmpty将空格也作为参数,isNotBlank则排除空格参数 参考 Quote StringUtils方法的操作对象是java.lang.String类型的对象,是JDK提供的String ...

  5. React Native混合开发中必须要学会点FlexBox布局

    在前面的案例中,界面的搭建都是采用CSS的布局,基于盒子模型,依赖 display属性 , position属性, float属性.但对于那些特殊布局非常不方便,比如,垂直居中. 一种全新的针对web ...

  6. 解析JDK动态代理实现原理

    JDK动态代理使用实例 代理模式的类图如上.关于静态代理的示例网上有很多,在这里就不讲了. 因为本篇讲述要点是JDK动态代理的实现原理,直接从JDK动态代理实例开始. 首先是Subject接口类. p ...

  7. java基础(5)--流程控制结构

    流程控制结构 if结构 当关系表达式为true时,执行语句 if(关系表达式){ //语句块 } if-else结构 当关系表达式为true时,执行语句块1,否则执行语句块2 if(关系表达式){ / ...

  8. LeetCode第[14]题(Java): Longest Common Prefix

    题目:最长公共前缀 难度:EASY 题目内容: Write a function to find the longest common prefix string amongst an array o ...

  9. SSH学习(2)

    SVN概述 1 SVN体系结构 (1)svn服务器 -首先在svn服务器里面创建 仓库 (2)svn客户端 SVN服务器安装和使用 0 首先把项目add到svn服务器上 清除不小点击保存密码的设置 修 ...

  10. 智课雅思词汇---二十三、名词性后缀mony

    智课雅思词汇---二十三.名词性后缀mony 一.总结 一句话总结:Latin: action, result of an action or condition; a suffix that for ...