老年选手不会 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. sql developer 如何格式化sql

    1.首先  Ctrl+A  全选需要格式的sql 2.然后  Ctrl+F7 即可格式化

  2. 【leetcode刷题笔记】Convert Sorted Array to Binary Search Tree

    Given an array where elements are sorted in ascending order, convert it to a height balanced BST. 题解 ...

  3. Spring 之自动化装配 bean 尝试

    [Spring之自动化装配bean尝试] 1.添加dependencies如下所示(不是每一个都用得到 <dependencies> <dependency> <grou ...

  4. pt-osc使用方法

    pt-osc实战运用 1.安装pt-osc,解压即可用 安装包在:10.135.2.217:data/online/software/percona-toolkit-3.0.12.tar.gz tar ...

  5. Python3,x:如何进行手机APP的数据爬取

    Python3,x:如何进行手机APP的数据爬取 一.简介 平时我们的爬虫多是针对网页的,但是随着手机端APP应用数量的增多,相应的爬取需求也就越来越多,因此手机端APP的数据爬取对于一名爬虫工程师来 ...

  6. 20145109 《Java实验报告1》

    Experiment Ⅰ --getting familiar with JDK (Linux + Eclipse) Content 1.Compile and run easy Java progr ...

  7. 利用Metasploit进行Linux提权

    利用Metasploit进行Linux提权 Metasploit 拥有msfpayload 和msfencode 这两个工具,这两个工具不但可以生成exe 型后门,一可以生成网页脚本类型的webshe ...

  8. Mybatis plus 高级

    最近项目重构 dao层使用的Mybatis plus,有必要总结下. Mybatis plus 会自动维护Mybatis 以及 MyBatis-Spring 相关依赖  所以在构建项目时候 只需要引入 ...

  9. 深入理解Java虚拟机(1)--Java内存区域

    运行时数据区域 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则是依赖用 ...

  10. 使用logrotate做nginx日志分割

    版权申明:转载请注明出处. 文章来源:http://bigdataer.net/?p=266 背景 nginx是一款非常优秀的网络代理工具,但是其日志管理有点缺憾:nginx的access_log会无 ...