[BZOJ4545]DQS的trie(广义后缀自动机+lct)
来源:互联网 发布:php storm10使用教程 编辑:程序博客网 时间:2024/05/16 01:38
题目描述
传送门
题目大意:
先给出一棵trie,然后支持几种操作
若opt=1,则是一组询问,询问当前trie的本质不同的子串数目是多少。
若opt=2,则后面跟两个整数rt,si,表示以点rt为根向下长出一个子树,大小为si。即加入一个子trie
若opt=3,则是一组询问,后面输入一个字符串S,询问字符串S在当前trie中的出现次数。
题解
这题其实是substring和生成魔咒的结合版
opt=1其实就是对于每一个主链上的点,求sigma step(i)-step(pre(i)),每一次extend的时候算一下就行了
opt=3是将S子在自动机上匹配之后求匹配到的点right集合的大小,也就是pa树上子树的大小,用lct维护一下
代码
#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<cmath>using namespace std;#define N 400005int T,n,m,mak,ans3;long long ans1;int mark[N],father[N],last[N];char s[N];int tot,point[N],nxt[N],v[N];char c[N];int root,sz,p,np,q,nq,pre[N],step[N],son[N][5];int f[N],ch[N][2],size[N],delta[N],stack[N];//----------------------------------lct--------------------------------------bool isroot(int x){ return ch[f[x]][0]!=x&&ch[f[x]][1]!=x;}int get(int x){ return ch[f[x]][1]==x;}void pushdown(int x){ if (x&&delta[x]) { int l=ch[x][0],r=ch[x][1]; if (l) size[l]+=delta[x],delta[l]+=delta[x]; if (r) size[r]+=delta[x],delta[r]+=delta[x]; delta[x]=0; }}void rotate(int x){ int old=f[x],oldf=f[old],wh=get(x); if (!isroot(old)) ch[oldf][ch[oldf][1]==old]=x; f[x]=oldf; ch[old][wh]=ch[x][wh^1]; if (ch[old][wh]) f[ch[old][wh]]=old; ch[x][wh^1]=old; f[old]=x;}void splay(int x){ int top=0;stack[++top]=x; for (int i=x;!isroot(i);i=f[i]) stack[++top]=f[i]; for (int i=top;i;--i) pushdown(stack[i]); for (int fa;!isroot(x);rotate(x)) if (!isroot(fa=f[x])) rotate(get(x)==get(fa)?fa:x);}void access(int x){ int t=0; for (;x;t=x,x=f[x]) { splay(x); ch[x][1]=t; }}void link(int x,int y){ f[y]=x; access(x); splay(x); size[x]+=size[y]; delta[x]+=size[y];}void cut(int x,int y){ access(y); splay(y); size[x]-=size[y]; delta[x]-=size[y]; ch[y][0]=f[x]=0;}//----------------------------------sam--------------------------------------void extend(int p,int x){ np=++sz; step[np]=step[p]+1; while (p&&!son[p][x]) { son[p][x]=np; p=pre[p]; } if (!p) { pre[np]=root; link(root,np); } else { q=son[p][x]; if (step[q]==step[p]+1) { pre[np]=q; link(pre[np],np); } else { nq=++sz; step[nq]=step[p]+1; pre[nq]=pre[q]; link(pre[nq],nq); memcpy(son[nq],son[q],sizeof(son[q])); while (p&&son[p][x]==q) { son[p][x]=nq; p=pre[p]; } cut(pre[q],q); pre[np]=pre[q]=nq; link(pre[q],q); link(pre[np],np); } } ans1+=(long long)step[np]-(long long)step[pre[np]]; access(np); splay(np); ++size[np]; ++delta[np];}int sam(){ int len=strlen(s);p=root; for (int i=0;i<len;++i) { int x=s[i]-'a'; p=son[p][x]; } if (!p) return 0; access(p); splay(p); return size[p];}//----------------------------------trie-------------------------------------void add(int x,int y,int z){ ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; c[tot]=z;}void dfs(int x,int fa,int mak){ father[x]=fa; for (int i=point[x];i;i=nxt[i]) if (v[i]!=fa&&mark[v[i]]==mak) { extend(last[x],c[i]); last[v[i]]=np; dfs(v[i],x,mak); }}//----------------------------------main-------------------------------------int main(){ scanf("%d",&T); scanf("%d",&n); root=++sz;last[1]=root; ++mak; for (int i=1;i<n;++i) { int x,y;char z;scanf("%d%d %c",&x,&y,&z); add(x,y,z-'a'),add(y,x,z-'a');mark[x]=mark[y]=mak; } dfs(1,0,mak); scanf("%d",&m); while (m--) { int opt;scanf("%d",&opt); if (opt==1) printf("%lld\n",ans1); else if (opt==2) { int ri,si;scanf("%d%d",&ri,&si); ++mak; for (int i=1;i<si;++i) { int x,y;char z;scanf("%d%d %c",&x,&y,&z); add(x,y,z-'a'),add(y,x,z-'a');mark[x]=mark[y]=mak; } dfs(ri,father[ri],mak); } else if (opt==3) { scanf("%s",s); ans3=sam(); printf("%d\n",ans3); } }}
0 0
- [BZOJ4545]DQS的trie(广义后缀自动机+lct)
- 后缀自动机+LCT 【bzoj4545】 DQS的Trie
- bzoj 4545: DQS的trie (后缀自动机+LCT)
- 【BZOJ4545】DQS的trie
- BZOJ4545 DQS的trie
- [bzoj4545] DQS的trie
- BJ模拟 Mr. Panda and Fantastic Beats(广义后缀自动机、trie树上后缀自动机)
- smoj2010(广义后缀自动机)
- [广义后缀自动机 Trie树] BZOJ 3926 [Zjoi2015]诸神眷顾的幻想乡
- 51nod 1647 小Z的trie 广义后缀自动机+倍增
- bzoj 2555: SubString (LCT+后缀自动机)
- [BZOJ2555]SubString(后缀自动机+lct)
- bzoj2555 -- 后缀自动机+LCT
- bzoj 3277: 串 (广义后缀自动机)
- smoj2257:宗教(广义后缀自动机)
- 广义后缀自动机
- bzoj3926 广义后缀自动机
- bzoj3926(广义后缀自动机)
- BFS例题
- 彻底解决 jspatch app store 审核通不过的问题
- linux驱动开发之字符设备框架
- Ajax请求Servlet返回文本 json html和XML数据并解析xml及responseText和responseXML的区别
- Javascript的数据类型
- [BZOJ4545]DQS的trie(广义后缀自动机+lct)
- javaWeb测试
- 深入理解JS—闭包
- 数据访问层
- 静态数据成员与静态成员函
- 文章标题
- 数据库的备份与还原
- [树链剖分]
- ZOJ 1006