BZOJ4545: DQS的trie
BZOJ4545: DQS的trie
https://lydsy.com/JudgeOnline/problem.php?id=4545
分析:
- 对trie用dfs建sam复杂度是\(O(n^2)\)的,因为你不能让一个复杂度带均摊的东西去一直回溯。
- 构造数据卡也很好卡,一条链边全是a,每个点连出去一条不是a的边。
- 于是我们用bfs建sam,这样复杂度是对的?
- 说这道题的做法,第一个询问每次插入时动态维护即可,第二问操作我们用lct维护后缀链接树。
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 400050
#define isrt(p) (ch[f[p]][1]!=p&&ch[f[p]][0]!=p)
typedef long long ll;
int ch[N][3],fa[N],len[N],cnt=1,pos[N],n;
ll nowans;
int head[N],to[N],nxt[N],CNT,val[N];
inline void add(int u,int v,int w) {
to[++CNT]=v; nxt[CNT]=head[u]; head[u]=CNT; val[CNT]=w;
}
int tr[N];
struct LCT {
#define ls ch[p][0]
#define rs ch[p][1]
#define get(x) (ch[f[x]][1]==x)
int ch[N][2],tag[N],f[N];
void rotate(int x) {
int y=f[x],z=f[y],k=get(x);
if(!isrt(y)) ch[z][ch[z][1]==y]=x;
ch[y][k]=ch[x][!k]; f[ch[y][k]]=y;
ch[x][!k]=y; f[y]=x; f[x]=z;
}
inline void giv(int p,int d) {
tag[p]+=d; tr[p]+=d;
}
inline void pushdown(int p) {
if(tag[p]) {
if(ls) giv(ls,tag[p]);
if(rs) giv(rs,tag[p]);
tag[p]=0;
}
}
void UPD(int p) {
if(!isrt(p)) UPD(f[p]);
pushdown(p);
}
void splay(int x) {
UPD(x);
for(int d;d=f[x],!isrt(x);rotate(x)) {
if(!isrt(d)) rotate(get(x)==get(d)?d:x);
}
}
void access(int p) {
int t=0;
while(p) {
splay(p); rs=t; t=p; p=f[p];
}
}
void cut(int p) {
access(p); splay(p); f[ls]=0; ls=0;
}
void link(int p,int q) {
f[p]=q;
}
}_;
int insert(int x,int lst) {
int p=lst,np,q,nq;
np=++cnt; lst=np;
len[np]=len[p]+1;
for(;p&&!ch[p][x];p=fa[p]) ch[p][x]=np;
if(!p) fa[np]=1,nowans+=len[np],_.link(np,1);
else {
q=ch[p][x];
if(len[q]==len[p]+1) fa[np]=q,nowans+=len[np]-(len[fa[np]]),_.link(np,q);
else {
nq=++cnt;
len[nq]=len[p]+1;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
_.UPD(q); tr[nq]=tr[q];
nowans-=(len[q]-len[fa[q]]);
fa[nq]=fa[q];
_.link(nq,fa[q]);
fa[q]=fa[np]=nq;
_.cut(q); _.link(q,nq); _.link(np,nq);
nowans+=(len[q]-len[fa[q]])+(len[nq]-len[fa[nq]])+(len[np]-len[fa[np]]);
for(;p&&ch[p][x]==q;p=fa[p]) ch[p][x]=nq;
}
}
_.access(lst), _.splay(lst), _.giv(lst,1);
return lst;
}
int Q[N];
bool vis[N];
void bfs(int x) {
int i,l=0,r=0;
Q[r++]=x; vis[x]=1;
while(l<r) {
x=Q[l++];
for(i=head[x];i;i=nxt[i]) if(!vis[to[i]]) {
vis[to[i]]=1; pos[to[i]]=insert(val[i],pos[x]); Q[r++]=to[i];
}
}
}
char w[N];
int main() {
scanf("%*d%d",&n);
int i,x,y;
pos[1]=1;
char oo[10];
for(i=1;i<n;i++) {
scanf("%d%d%s",&x,&y,oo+1);
add(x,y,oo[1]-'a'),add(y,x,oo[1]-'a');
}
bfs(1);
int m;
scanf("%d",&m);
int sz;
while(m--) {
int opt;
scanf("%d",&opt);
if(opt==1) {
printf("%lld\n",nowans);
}else if(opt==2) {
int rt;
scanf("%d%d",&rt,&sz); head[rt]=0;
for(i=1;i<sz;i++) {
scanf("%d%d%s",&x,&y,oo+1);
add(x,y,oo[1]-'a'), add(y,x,oo[1]-'a');
}
bfs(rt);
}else {
scanf("%s",w+1);
int k=strlen(w+1),p=1;
for(i=1;i<=k;i++) {
x=w[i]-'a';
if(ch[p][x]) p=ch[p][x];
else {p=ch[p][x]; break;}
}
if(!p) {puts("0");continue ;}
_.splay(p);
printf("%d\n",tr[p]);
}
}
}
BZOJ4545: DQS的trie的更多相关文章
- BZOJ4545: DQS的trie 广义后缀自动机_LCT
特别鸣神犇 fcwww 替我调出了无数个错误(没他的话我都快自闭了),祝大佬省选rp++ 板子题,给我写了一天QAQ...... 用 LCT 维护后缀树,暴力更新用 LCT 区间更新链即可 其实,在计 ...
- 【BZOJ4545】DQS的trie 后缀自动机+LCT
[BZOJ4545]DQS的trie Description DQS的自家阳台上种着一棵颗粒饱满.颜色纯正的trie. DQS的trie非常的奇特,它初始有n0个节点,n0-1条边,每条边上有一个字符 ...
- bzoj 4545: DQS的trie
Description DQS的自家阳台上种着一棵颗粒饱满.颜色纯正的trie. DQS的trie非常的奇特,它初始有n0个节点,n0-1条边,每条边上有一个字符.并且,它拥有极强的生长力:某个i时刻 ...
- bzoj 4545 DQS 的 Trie
老年选手不会 SAM 也不会 LCT 系列 我的数据结构好菜啊 qnq 一颗 Trie 树,$q$ 次询问,每次可以是: 1.求这棵树上本质不同的子串数量 2.插入一个子树,保证总大小不超过 $100 ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- 基于trie树做一个ac自动机
基于trie树做一个ac自动机 #!/usr/bin/python # -*- coding: utf-8 -*- class Node: def __init__(self): self.value ...
- 基于trie树的具有联想功能的文本编辑器
之前的软件设计与开发实践课程中,自己构思的大作业题目.做的具有核心功能,但是还欠缺边边角角的小功能和持久化数据结构,先放出来,有机会一点点改.github:https://github.com/chu ...
- [LeetCode] Implement Trie (Prefix Tree) 实现字典树(前缀树)
Implement a trie with insert, search, and startsWith methods. Note:You may assume that all inputs ar ...
- hihocoder-1014 Trie树
hihocoder 1014 : Trie树 link: https://hihocoder.com/problemset/problem/1014 题意: 实现Trie树,实现对单词的快速统计. # ...
随机推荐
- [CMD]重启电脑
https://zhidao.baidu.com/question/686086701903450132.html bat是批处理,可以调用关机命令关机. 制作方法如下: 打开记事本程序: 输入如下内 ...
- 【BZOJ3105】[cqoi2013]新Nim游戏 贪心+线性基
[BZOJ3105][cqoi2013]新Nim游戏 Description 传统的Nim游戏是这样的:有一些火柴堆,每堆都有若干根火柴(不同堆的火柴数量可以不同).两个游戏者轮流操作,每次可以选一个 ...
- C++模板类[初步]
/* * stacktp.h * * Created on: 2014年3月29日 * Author: */ /** * - 模板类的概念,与使用 * -# export template <c ...
- 九度OJ 1190:大整数排序 (大数运算、排序)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:3219 解决:1467 题目描述: 对N个长度最长可达到1000的数进行排序. 输入: 输入第一行为一个整数N,(1<=N<=1 ...
- GCD多线程在swift中的变化
1.异步线程加载主线程刷新 DispatchQueue.global().async { // TODO:执行异步线程网络请求 DispatchQueue.main.async(execute: { ...
- 【学员管理系统】0x04 数据库连接优化
[学员管理系统]0x04 pymysql数据库连接优化 写在前面 项目详细需求参见:Django项目之[学员管理系统] 优化实现 把操作封装成函数 我们之前使用pymysql操作数据库的操作都是写死 ...
- PAT 1051. 复数乘法 (15)
复数可以写成(A + Bi)的常规形式,其中A是实部,B是虚部,i是虚数单位,满足i2 = -1:也可以写成极坐标下的指数形式(R*e(Pi)),其中R是复数模,P是辐角,i是虚数单位,其等价于三角形 ...
- [ACM] FZU 2087 统计数边 (有多少边至少存在一个最小生成树里面)
Problem Description 在图论中,树:随意两个顶点间有且仅仅有一条路径的图. 生成树:包括了图中全部顶点的一种树. 最小生成树:对于连通的带权图(连通网)G,其生成树也是带权的. 生成 ...
- linux c编程:进程控制(三)_exec函数
fork()函数通过系统调用创建一个与原来进程(父进程)几乎完全相同的进程(子进程是父进程的副本,它将获得父进程数据空间.堆.栈等资源的副本.注意,子进程持有的是上述存储空间的“副本”,这意味着父子进 ...
- ubuntun下安装Fiddler
对于分析网页或者写爬虫的时候经常需要用到抓包工具进行网页数据的抓包.在Windows下可以安装Fiddler来抓包.在ubuntun下不能直接安装Fiddler.需要先安装mono 1 首先安装mon ...