bzoj 4545: DQS的trie
Description
DQS的自家阳台上种着一棵颗粒饱满、颜色纯正的trie。
DQS的trie非常的奇特,它初始有n0个节点,n0-1条边,每条边上有一个字符。并且,它拥有极强的生长力:某个i时刻,某个节点就会新生长出一颗子树,它拥有si个节点且节点之间的边上有一个字符,并且新生长出来的子树也是一个树结构。然而因为是新长出来的,根据生活常识可知si必定不会大于i时刻之前的树的大小。
DQS定义trie的子串为从根节点(1号节点)往下走到所有节点所构成的字符串的所有的后缀。DQS身为一个单身doge,常常取出其中一个子串送给妹子,然而他并不希望送给妹子两个相同的子串,所以他非常关心当前trie的本质不同的子串数目。
DQS有时还会去商店购买子串,若他在商店看上某个子串,他希望得知这个子串是否在自家阳台的trie上已经出现,若出现则出现了多少次。如果出现了,他就可以直接回家取trie上的子串辣!
然而DQS身为一个蒟蒻,看着自家阳台的trie树一天天在长大,他被如此众多的节点弄得眼花缭乱,于是他找到了IOI2016Au的你。他会告诉你自家trie树的成长历程,他希望你能够对于每一次询问都做出正确回复。
Input
第一行输入一个整数id,代表测试点编号。
接下来一行输入一个整数n0,表示初始树的大小。
接下来n0-1行,每行两个整数u,v和一个字符c,表示u号节点和v号节点之间有一条边,边上的字母为c。
接下来输入m表示有m组操作。
对于每一组,第一行输入一个整数opt。
若opt=1,则是一组询问,询问当前trie的本质不同的子串数目是多少。
若opt=2,则后面跟两个整数rt,si,表示以点rt为根向下长出一个子树,大小为si。
接下来si-1行,每行两个整数u,v和一个字符c,表示u号节点和v号节点之间有一条边,边上的字母为c。若长出子树之前当前树的大小是n,则这si-1点的编号分别为n+1,n+2…n+si-1。
若opt=3,则是一组询问,后面输入一个字符串S,询问字符串S在当前trie中的出现次数。
Solution
比较直观
操作 \(1\) ,就是维护 \(\sum len[x]-len[fa[x]]\) ,改变父亲关系时加减一下就好了
然而在加入一个 \(nt\) 的时候,把式子列出来发现直接抵消了,\(QAQ\)
实际上维护一下 \(cur\) 的变化就好了
操作 \(2,3\) 和 \(substring\) 一题类似, \(LCT\) 维护链加法就好了
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
template<class T>void gi(T &x){
int f;char c;
for(f=1,c=getchar();c<'0'||c>'9';c=getchar())if(c=='-')f=-1;
for(x=0;c<='9'&&c>='0';c=getchar())x=x*10+(c&15);x*=f;
}
const int N=2e5+10;
namespace lct{
int fa[N],ch[N][2],w[N],la[N];
inline bool isrt(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
inline void mark(int x,int t){la[x]+=t;w[x]+=t;}
inline void pushdown(int x){
if(!la[x])return ;
mark(ch[x][0],la[x]);mark(ch[x][1],la[x]);la[x]=0;
}
inline void rotate(int x){
int y=fa[x];bool t=ch[y][1]==x;
ch[y][t]=ch[x][!t];fa[ch[y][t]]=y;
ch[x][!t]=y;fa[x]=fa[y];
if(!isrt(y))ch[fa[y]][ch[fa[y]][1]==y]=x;
fa[y]=x;
}
inline void Push(int x){
if(!isrt(x))Push(fa[x]);
pushdown(x);
}
inline void splay(int x){
Push(x);
while(!isrt(x)){
int y=fa[x],p=fa[y];
if(isrt(y))rotate(x);
else if((ch[p][0]==y)==(ch[y][0]==x))rotate(y),rotate(x);
else rotate(x),rotate(x);
}
}
inline void access(int x){
int y=0;
while(x)splay(x),ch[x][1]=y,x=fa[y=x];
}
inline void link(int x,int y){
fa[x]=y;access(y);splay(y);splay(x);mark(y,w[x]);
}
inline void cut(int x){
access(x);splay(x);mark(ch[x][0],-w[x]);ch[x][0]=fa[ch[x][0]]=0;
}
inline int qry(int x){splay(x);return w[x];}
}
int n,Q,head[N],nxt[N*2],to[N*2],num=0,c[N],las[N],cnt=1,cur;
ll ans=0;int ch[N][26],fa[N],len[N];char s[N];
inline void link(int x,int y,int z){
nxt[++num]=head[x];to[num]=y;head[x]=num;c[num]=z;
nxt[++num]=head[y];to[num]=x;head[y]=num;c[num]=z;
}
inline void ins(int c,int p){
cur=++cnt;len[cur]=len[p]+1;lct::w[cur]=1;
for(;p && !ch[p][c];p=fa[p])ch[p][c]=cur;
if(!p)fa[cur]=1,lct::link(cur,1);
else{
int q=ch[p][c];
if(len[p]+1==len[q])fa[cur]=q,lct::link(cur,q);
else{
int nt=++cnt;len[nt]=len[p]+1;
memcpy(ch[nt],ch[q],sizeof(ch[q]));
lct::cut(q);lct::link(nt,fa[q]);lct::link(q,nt);lct::link(cur,nt);
fa[nt]=fa[q];fa[q]=fa[cur]=nt;
for(;p && ch[p][c]==q;p=fa[p])ch[p][c]=nt;
}
}
ans+=len[cur]-len[fa[cur]];
}
inline void bfs(int S){
queue<int>Q;Q.push(S);
while(!Q.empty()){
int x=Q.front();Q.pop();
for(int i=head[x],u;i;i=nxt[i]){
if(las[u=to[i]])continue;
ins(c[i],las[x]);las[u]=cur;Q.push(u);
}
}
}
inline int solve(){
scanf("%s",s+1);
int le=strlen(s+1),p=1;
for(int i=1;i<=le;i++){
int c=s[i]-'a';
if(ch[p][c])p=ch[p][c];
else return 0;
}
return lct::qry(p);
}
int main(){
freopen("pp.in","r",stdin);
freopen("pp.out","w",stdout);
gi(n);gi(n);
int x,y,op,p,q;char ch[2];
for(int i=1;i<n;i++)gi(x),gi(y),scanf("%s",ch),link(x,y,ch[0]-'a');
bfs(las[1]=1);gi(Q);
while(Q--){
gi(op);
if(op==1)printf("%lld\n",ans);
else if(op==2){
gi(p);gi(q);
for(int i=1;i<q;i++){
gi(x),gi(y),scanf("%s",ch);
link(x,y,ch[0]-'a');
}
bfs(p);
}else printf("%d\n",solve());
}
return 0;
}
bzoj 4545: DQS的trie的更多相关文章
- bzoj 4545 DQS 的 Trie
老年选手不会 SAM 也不会 LCT 系列 我的数据结构好菜啊 qnq 一颗 Trie 树,$q$ 次询问,每次可以是: 1.求这棵树上本质不同的子串数量 2.插入一个子树,保证总大小不超过 $100 ...
- BZOJ4545: DQS的trie
BZOJ4545: DQS的trie https://lydsy.com/JudgeOnline/problem.php?id=4545 分析: 对trie用dfs建sam复杂度是\(O(n^2)\) ...
- 【BZOJ4545】DQS的trie 后缀自动机+LCT
[BZOJ4545]DQS的trie Description DQS的自家阳台上种着一棵颗粒饱满.颜色纯正的trie. DQS的trie非常的奇特,它初始有n0个节点,n0-1条边,每条边上有一个字符 ...
- BZOJ 4545
bzoj 4545 给定一个踹树,支持几种操作. 本质不同子串询问 加入子树 询问字符串\(S\) 在树上的出现次数. 好码好码 重点就是维护\(parent\) 树,考虑用\(LCT\)维护此树. ...
- BZOJ 4260: Codechef REBXOR( trie )
求出前缀和, 那么以第x个元素结尾的最大异或值是max(sumx^sump)(1≤p<x), 用trie加速. 后缀同理, 然后扫一遍就OK了.时间复杂度O(31N) ------------- ...
- BZOJ 3689 异或 Trie木+堆
标题效果:特定n的数量,这种需求n数22 XOR的值前者k少 首先,我们建立了一个二进制的所有数字Trie木,您可以使用Trie木size域检查出一些其他的数字XOR值首先k少 然后,我们要保持一个堆 ...
- bzoj 2741 可持久化trie
首先我们设si为前i个数的xor和,那么对于询问区间[i,j]的xor和,就相当于si-1^sj,那么对于这道题的询问我们可以处理处si,然后对于询问[l,r],可以表示为在区间[l-1,r]里找两个 ...
- BZOJ - 3166 可持久化Trie 维护次大区间
题意:给出\(a[1...n]\),找出一个连续区间\(a[l...r],r>l\),令该区间的次大值为\(a_k\),使得\(a_k⊕a_i,l≤i≤r\)最大,输出全局最优解 (这题意有点别 ...
- bzoj 1819: 电子字典 Trie
题目: Description 人们在英文字典中查找某个单词的时候可能不知道该单词的完整拼法,而只知道该单词的一个错误的近似拼法,这时人们可能陷入困境,为了查找一个单词而浪费大量的时间.带有模糊查询功 ...
随机推荐
- UserControl 用户定义组件
<pages> <namespaces> <add namespace="System.Web.Optimization" /> </na ...
- Beta版本展示博客
1 团队介绍 团队组成: 齐爽爽(258)个人博客:http://www.cnblogs.com/shuangshuangblog/ 马帅(248)个人博客:http://www.cnblogs.co ...
- jwt验证登录信息
为什么要告别session?有这样一个场景,系统的数据量达到千万级,需要几台服务器部署,当一个用户在其中一台服务器登录后,用session保存其登录信息,其他服务器怎么知道该用户登录了?(单点登录), ...
- WPF自学入门(十)WPF MVVM简单介绍
前面文章中,我们已经知道,WPF技术的主要特点是数据驱动UI,所以在使用WPF技术开发的过程中是以数据为核心的,WPF提供了数据绑定机制,当数据发生变化时,WPF会自动发出通知去更新UI. 我们不管 ...
- 构建自己的 PHP 框架
这是一个系列的文章,项目地址在这里,欢迎大家star. 这个框架前一部分比较像Yii,后一部分比较像Laravel,因为当时正在看相应框架的源码,所以会有不少借鉴参考.捂脸- 这个框架千万不要直接应用 ...
- js前端对后台数据的获取,如果是汉字则需要添上引号
js前端对后台数据的获取,如果是汉字则需要添上引号
- MySQL 主从复制那些事(一)
本部分主要以理论为主,具体的主从搭建环境,大家可以参考博客其他部分.下面我就给大家数说主从复制那些理论的东西.说的不一定都是正确的,有不同出入的地方,欢迎大家一起交流沟通,以下我把我自己整理出来的主从 ...
- Python内置函数(17)——chr
英文文档: chr(i) Return the string representing a character whose Unicode code point is the integer i. F ...
- python网络爬虫与信息提取 学习笔记day2
Day2: 查看robots协议: 查看京东的robots协议 查看百度的robots协议,可以看到百度拒绝了搜狗的爬虫233 爬取京东商品页面相关信息: import requests url = ...
- Python之面向对象二
面向对象的三大特性: 继承 继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类 python中类的继承分为:单继承和多继承 c ...