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的更多相关文章

  1. BZOJ4545: DQS的trie 广义后缀自动机_LCT

    特别鸣神犇 fcwww 替我调出了无数个错误(没他的话我都快自闭了),祝大佬省选rp++ 板子题,给我写了一天QAQ...... 用 LCT 维护后缀树,暴力更新用 LCT 区间更新链即可 其实,在计 ...

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

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

  3. bzoj 4545: DQS的trie

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

  4. bzoj 4545 DQS 的 Trie

    老年选手不会 SAM 也不会 LCT 系列 我的数据结构好菜啊 qnq 一颗 Trie 树,$q$ 次询问,每次可以是: 1.求这棵树上本质不同的子串数量 2.插入一个子树,保证总大小不超过 $100 ...

  5. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  6. 基于trie树做一个ac自动机

    基于trie树做一个ac自动机 #!/usr/bin/python # -*- coding: utf-8 -*- class Node: def __init__(self): self.value ...

  7. 基于trie树的具有联想功能的文本编辑器

    之前的软件设计与开发实践课程中,自己构思的大作业题目.做的具有核心功能,但是还欠缺边边角角的小功能和持久化数据结构,先放出来,有机会一点点改.github:https://github.com/chu ...

  8. [LeetCode] Implement Trie (Prefix Tree) 实现字典树(前缀树)

    Implement a trie with insert, search, and startsWith methods. Note:You may assume that all inputs ar ...

  9. hihocoder-1014 Trie树

    hihocoder 1014 : Trie树 link: https://hihocoder.com/problemset/problem/1014 题意: 实现Trie树,实现对单词的快速统计. # ...

随机推荐

  1. static全局变量与普通的全局变量有什么区别?static局部变量和普通局部变量有什么区别?static函数与普通函数有什么区别?

    答案:全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量.全局变量本身就是静态存储方式,静态全局变量当然也是静态存储方式. 这两者在存储方式上并无不同.这两者的区别虽在于非静态全 ...

  2. c#中关于compare比较的一点注意事项

    一直没有太注意,今天发现在compare比较两个字符串的时候出了点小问题 如果我设置了两个字符串 一个是“2”,一个是“12” 那么在比较的时候 第一个会大于第二个: 如果第一个是“02”,第二个是“ ...

  3. Windows 下Node.js开发环境配置

    第一步:安装VirtualBox(以管理员身份安装) 1.安装完成后,打开VirtualBox,点击“新建”按钮,输入信息,“下一步”(名称可任意) 2.设置内存为1024MB,“下一步”—>“ ...

  4. SQL SERVER 2008查看sql执行的时间

    set statistics profile onset statistics io onset statistics time ongo<这里写上你的语句...>goset statis ...

  5. vue组件父子组件之间传递数据

    举个栗子: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF ...

  6. AFN多文件进度下载

    AFN参考资料 http://www.jianshu.com/p/c36159094e24 http://blog.cnbang.net/tech/2320/http://blog.cnbang.ne ...

  7. Centos 6 安装 python2.7 和 pip

    一.安装 python2.7 [root@crazy-acong ~]# cd /data/tools/ [root@crazy-acong tools]# yum groupinstall &quo ...

  8. [IOI2018]组合动作

    IOI2018 组合动作 UOJ 首先显然可以两次试出首字母 考虑增量构造 假设首字母为A,且已经试出前i个字母得到的串s 我们考虑press这样一个串s+BB+s+BX+s+BY+s+XA 首先这个 ...

  9. 我的Android进阶之旅------>Android基于HTTP协议的多线程断点下载器的实现

    一.首先写这篇文章之前,要了解实现该Android多线程断点下载器的几个知识点 1.多线程下载的原理,如下图所示 注意:由于Android移动设备和PC机的处理器还是不能相比,所以开辟的子线程建议不要 ...

  10. OutOfMemoryError: Java heap space和GC overhead limit exceeded在Ant的Build.xml中的通用解决方式

    这个仅仅是一点点经验,总结一下,当中前两个相应第一个Error.后两个相应第二个Error,假设heap space还不够.能够再改大些. <jvmarg value="-Xms512 ...