【BZOJ4545】DQS的trie 后缀自动机+LCT
【BZOJ4545】DQS的trie
Description
Input
Output
Sample Input
4
1 2 a
1 3 b
2 4 b
6
1
2 2 4
2 5 b
2 6 c
5 7 b
1
3 ab
2 6 3
6 8 a
6 9 b
1
Sample Output
7
2
11
【数据范围及提示】
第一个询问,本质不同的子串是 a,b,ab。
第二个询问,本质不同的子串是 a,b,c,ab,ac,bb,abb。
第三个询问,ab出现次数是 2。
第四个询问,本质不同的子串是 a,b,c,ab,ac,ca,cb,bb,abb,aca,acb。
opt=1或3时对原树不做修改,只是询问。
每次opt=2,会增加si-1个节点,因为有一个节点是原树上作为新树的根出现的。
数据中,对于链的部分分,满足端点为根节点,每次新建子树都从尾部插入。
对于全部数据,保证从始至终每条边上的字符均为小写字母’a’或’b’或’c’。
n是最终树的大小,N<=100000,M<=100000,Si<=当前树的大小
题解:本题就是3998和2555的结合体,没做过的直接去做那两题吧。
对于第一问,我们可以动态维护所有点的mx[i]-mx[pre]之和,对于第二问,用LCT维护pre树,并将 插入一棵子树,求一个点的子树大小 变成 修改一条链上的权值,查询一个点的值 即可。
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn=400010;
typedef long long ll;
int n,m,tot,len,cnt;
int to[maxn],next[maxn],val[maxn],head[maxn],pos[maxn];
ll ans;
char str[maxn];
namespace LCT
{
struct node
{
int ch[2],fa;
ll tag,val;
}s[maxn];
int st[maxn],top;
inline bool isr(int x) {return (x!=s[s[x].fa].ch[0])&&(x!=s[s[x].fa].ch[1]);}
inline void pushdown(int x)
{
if(s[x].tag)
{
if(s[x].ch[0]) s[s[x].ch[0]].val+=s[x].tag,s[s[x].ch[0]].tag+=s[x].tag;
if(s[x].ch[1]) s[s[x].ch[1]].val+=s[x].tag,s[s[x].ch[1]].tag+=s[x].tag;
s[x].tag=0;
}
}
inline void rotate(int x)
{
int y=s[x].fa,z=s[y].fa,d=(x==s[y].ch[1]);
if(!isr(y)) s[z].ch[y==s[z].ch[1]]=x;
s[x].fa=z,s[y].fa=x,s[y].ch[d]=s[x].ch[d^1];
if(s[x].ch[d^1]) s[s[x].ch[d^1]].fa=y;
s[x].ch[d^1]=y;
}
inline void updata(int x)
{
int y=x;
st[top=1]=x;
while(!isr(y)) y=s[y].fa,st[++top]=y;
while(top) pushdown(st[top--]);
}
inline void splay(int x)
{
updata(x);
while(!isr(x))
{
int y=s[x].fa,z=s[y].fa;
if(!isr(y))
{
if((x==s[y].ch[0])^(y==s[z].ch[0])) rotate(x);
else rotate(y);
}
rotate(x);
}
}
inline void access(int x)
{
for(int y=0;x;splay(x),s[x].ch[1]=y,y=x,x=s[x].fa);
}
inline void link(int x,int y)
{
access(x),splay(x),s[y].fa=x,s[x].val+=s[y].val,s[x].tag+=s[y].val;
}
inline void cut(int x)
{
access(x),splay(x),s[s[x].ch[0]].val-=s[x].val,s[s[x].ch[0]].tag-=s[x].val;
s[s[x].ch[0]].fa=0,s[x].ch[0]=0;
}
}
namespace SAM
{
int ch[maxn][26],pre[maxn],mx[maxn];
char str[maxn];
inline int extend(int p,int x)
{
int np=++tot;
mx[np]=mx[p]+1,LCT::s[np].val=1;
for(;p&&!ch[p][x];p=pre[p]) ch[p][x]=np;
if(!p) pre[np]=1,ans+=mx[np],LCT::link(1,np);
else
{
int q=ch[p][x];
if(mx[q]==mx[p]+1) pre[np]=q,ans+=mx[np]-mx[q],LCT::link(q,np);
else
{
int nq=++tot; mx[nq]=mx[p]+1;
ans-=mx[q]-mx[pre[q]];
LCT::cut(q);
pre[nq]=pre[q],pre[np]=pre[q]=nq;
ans+=mx[nq]-mx[pre[nq]]+mx[np]-mx[pre[np]]+mx[q]-mx[pre[q]];
LCT::link(pre[nq],nq),LCT::link(pre[q],q),LCT::link(pre[np],np);
memcpy(ch[nq],ch[q],sizeof(ch[q]));
for(;p&&ch[p][x]==q;p=pre[p]) ch[p][x]=nq;
}
}
return np;
}
inline void query()
{
scanf("%s",str),len=strlen(str);
int i,p=1;
for(i=0;i<len&&p;i++) p=ch[p][str[i]-'a'];
if(!p) puts("0");
else
{
LCT::updata(p);
printf("%lld\n",LCT::s[p].val);
}
}
}
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+(gc^'0'),gc=getchar();
return ret*f;
}
void dfs(int x,int fa)
{
for(int i=head[x];i!=-1;i=next[i]) if(to[i]!=fa) pos[to[i]]=SAM::extend(pos[x],val[i]),dfs(to[i],x);
head[x]=-1;
}
inline void add(int a,int b,int c)
{
to[cnt]=b,val[cnt]=c,next[cnt]=head[a],head[a]=cnt++;
}
int main()
{
rd(),n=rd();
int i,a,b,c,d,op;
tot=1,pos[1]=1;
memset(head,-1,sizeof(head));
for(i=1;i<n;i++) a=rd(),b=rd(),scanf("%s",str),add(a,b,str[0]-'a'),add(b,a,str[0]-'a');
dfs(1,0);
m=rd();
for(i=1;i<=m;i++)
{
op=rd();
if(op==1) printf("%lld\n",ans);
if(op==2)
{
c=rd(),d=rd();
while(--d) a=rd(),b=rd(),scanf("%s",str),add(a,b,str[0]-'a'),add(b,a,str[0]-'a');
dfs(c,0);
}
if(op==3) SAM::query();
}
return 0;
}//1 4 1 2 a 1 3 b 2 4 b 6 1 2 2 4 2 5 b 2 6 c 5 7 b 1 3 ab 2 6 3 6 8 a 6 9 b 1
【BZOJ4545】DQS的trie 后缀自动机+LCT的更多相关文章
- BZOJ4545: DQS的trie
BZOJ4545: DQS的trie https://lydsy.com/JudgeOnline/problem.php?id=4545 分析: 对trie用dfs建sam复杂度是\(O(n^2)\) ...
- BZOJ4545: DQS的trie 广义后缀自动机_LCT
特别鸣神犇 fcwww 替我调出了无数个错误(没他的话我都快自闭了),祝大佬省选rp++ 板子题,给我写了一天QAQ...... 用 LCT 维护后缀树,暴力更新用 LCT 区间更新链即可 其实,在计 ...
- bzoj2555(后缀自动机+LCT)
题目描述 (1):在当前字符串的后面插入一个字符串 (2):询问字符串s在当前字符串中出现了几次?(作为连续子串) 你必须在线支持这些操作. 题解 做法很自然,建出后缀自动机,维护每个节点的right ...
- 51nod 1600 Simple KMP【后缀自动机+LCT】【思维好题】*
Description 对于一个字符串|S|,我们定义fail[i],表示最大的x使得S[1..x]=S[i-x+1..i],满足(x<i) 显然对于一个字符串,如果我们将每个0<=i&l ...
- BZOJ2555 SubString 【后缀自动机 + LCT】
题目 懒得写背景了,给你一个字符串init,要求你支持两个操作 (1):在当前字符串的后面插入一个字符串 (2):询问字符串s在当前字符串中出现了几次?(作为连续子串) 你必须在线支持这些操作. 输入 ...
- bzoj 2555 SubString —— 后缀自动机+LCT
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2555 建立后缀自动机,就可以直接加入新串了: 出现次数就是 Right 集合的大小,需要查询 ...
- bzoj 2555: SubString【后缀自动机+LCT】
一直WA--找了半天错的发现居然是解密那里的mask其实是不能动的--传进去的会变,但是真实的那个不会变-- 然后就是后缀自动机,用LCT维护parent树了--注意不能makeroot,因为自动机的 ...
- bzoj 2555: SubString 后缀自动机+LCT
2555: SubString Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 688 Solved: 235[Submit][Status][Dis ...
- BZOJ2555 SubString【后缀自动机+LCT】
Description 懒得写背景了,给你一个字符串init,要求你支持两个操作 (1):在当前字符串的后面插入一个字符串 (2):询问字符串s在当前字符串中出现了几次?(作为连续子串) 你必须在线支 ...
随机推荐
- RTMP规范 消息与消息块
Real Time Messaging Protocol(实时消息传输协议) 应用层协议 RTMP协议中, 基本数据单元称为消息(Message).当RTMP协议在互联网中传输数据的时候,消息会被拆分 ...
- d3js把circle和rect连接在一起
怎么办呢...哎...突然就必须全选中了.... 但是...一不小心想到 在g里面都添加circle和rect 但是根据tpye可以让circle的r为0或者rect的width和height为0,这 ...
- 第二百九十八节,python操作redis缓存-Set集合类型,可以理解为不能有重复元素的列表
python操作redis缓存-Set集合类型,可以理解为不能有重复元素的列表 sadd(name,values)name对应的集合中添加元素 #!/usr/bin/env python # -*- ...
- 图像处理之3d算法----2d转3d算法介绍
http://www.3dov.cn/html/c/37/index.html http://news.ifeng.com/a/20151117/46275220_0.shtml 磁力矩阵 http: ...
- 关于HTTP keep-alive的实验(转至 http://my.oschina.net/flashsword/blog/80037)
前面一篇文章提到,HTTP1.1中持久连接已经是默认配置,除非设置Connection为close,否则默认都会进行持久连接.但是我们知道事实标准跟教科书还是可能会有一定差距的,所以不妨自己尝试一下. ...
- vncserver的安装和使用
环境:RedHat Linux 6企业版.Xwindows:gnome (红帽默认安装的图形界面) 尽管我们可以使用SSH连接远程通过字符界面来操作Linux,但是对于更多熟悉图形人来说是很不方便的, ...
- ImportError: No module named Crypto.Cipher
from Crypto.Cipher import AES 报错: ImportError: No module named Crypto.Cipher 解决方法: pip install pycry ...
- 使用PHP生成和获取XML格式数据
1.php生成xml
- [转]anchorPoint 锚点解析
转自:http://blog.csdn.net/cjopengler/article/details/7045638 anchor point 究竟是怎么回事? 之所以造成不容易理解的是因为我们平时看 ...
- Phpcms V9当前栏目及所有二级栏目下内容调用标签
在二级栏目列表页调用: <!--* 获取子栏目* @param $parentid 父级id* @param $type 栏目类型* @param $self 是否包含本身 0为不包含* @pa ...