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树,实现对单词的快速统计. # ...
随机推荐
- poj 3468 Splay 树
大二上的时候.写过一个AVL的操作演示,今天一看Splay.发现和AVL事实上一样,加上线段树的基础,懒惰标记什么都知道.学起来轻松很多哦 我參考的模板来自这里 http://blog.csdn.n ...
- pthon 基础 9.8 增加数据
#/usr/bin/python #-*- coding:utf-8 -*- #@Time :2017/11/24 2:59 #@Auther :liuzhenchuan #@File :增加 ...
- Virtualbox报错------> '/etc/init.d/vboxdrv setup'
Ubuntu下VirtualBox本来可以很好地用的,今天早上一来就报错了,--提示如下内容: ---------------------------------------------------- ...
- hibernate 多对多 懒加载问题
报错:org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: net. ...
- python初学者总结
学习python首先配置好工作环境,因为不同版本之间的python是不兼容了 原创:01coding.com win7安装环境过程: 1:下载python 建议下载两个不同版本官方已给出 https: ...
- spark在yarn-cluster上面执行报错
在单机模式下执行成功的spark程序,在yarn上面就报错.异常信息如下: // :: INFO DAGScheduler: Completed ResultTask(, ) // :: INFO D ...
- vue页面性能优化方案
个人在项目中用到的页面性能优化的方式总结. 一.均衡页面加载文件的大小和数量 1.项目中小图片图片转base64,通过工具如webpack进行图片压缩,文件进行压缩混淆等 2.vue-router 懒 ...
- Data Structure Binary Tree: Iterative Postorder Traversal
http://www.geeksforgeeks.org/iterative-postorder-traversal-using-stack/ #include <iostream> #i ...
- css3条纹边框效果
在线演示 本地下载
- 比较分析与数组相关的sizeof和strlen
首先,我们要清楚sizeof是C/C++中的一个操作符,其作用就是返回一个对象或者类型所占的内存字节数. 而,strlen是一个函数,函数原型为: size_t strlen(const char * ...