【BZOJ4545】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中的出现次数。
Output
对于每个opt=1或3,输出一行表示答案。
Sample Input
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
Sample Output
3
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<=当前树的大小
HINT
Source
By Loi_DQS
裸SAM+LCT
抄一下2555以前写的代码
出题人强行放到trie上真是差评不已
总结一下就是这题是个SAM辣鸡题..
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define LL long long
#define MAXN 200010
#define GET (ch>='0'&&ch<='9')
#define is_root(x) (tree[tree[x].fa].ch[0]!=x&&tree[tree[x].fa].ch[1]!=x)
using namespace std;
LL ans;
int n,m,top,tp;
bool vis[MAXN];
int sta[MAXN],num[MAXN],fa[MAXN];
char s[MAXN];
inline void in(int &x)
{char ch=getchar();x=0;while (!GET) ch=getchar();while (GET) x=x*10+ch-'0',ch=getchar();
}
struct Splay { int ch[2],fa,sum,flag; }tree[MAXN];
struct edge { int to,w; edge *next; }e[MAXN<<1],*prev[MAXN];
inline void insert(int u,int v,int w) { e[++top].to=v;e[top].w=w;e[top].next=prev[u];prev[u]=&e[top]; }
inline void add(int x,int v) { if (x) tree[x].sum+=v;tree[x].flag+=v; }
inline void push_down(int x)
{if (tree[x].flag) add(tree[x].ch[0],tree[x].flag),add(tree[x].ch[1],tree[x].flag),tree[x].flag=0;
}
inline void rot(int x)
{int y=tree[x].fa,z=tree[y].fa,l=(tree[y].ch[1]==x),r=l^1;if (!is_root(y)) tree[z].ch[tree[z].ch[1]==y]=x;tree[tree[x].ch[r]].fa=y;tree[y].fa=x;tree[x].fa=z;tree[y].ch[l]=tree[x].ch[r];tree[x].ch[r]=y;
}
inline void Splay(int x)
{tp=0;sta[++tp]=x;for (int i=x;!is_root(i);i=tree[i].fa) sta[++tp]=tree[i].fa;while (tp) push_down(sta[tp--]);while (!is_root(x)){int y=tree[x].fa,z=tree[y].fa;if (!is_root(y)){if ((tree[y].ch[0]==x)^(tree[z].ch[0]==y)) rot(x);else rot(y);}rot(x);}
}
inline void access(int x) { for (int i=0;x;i=x,x=tree[x].fa) Splay(x),tree[x].ch[1]=i; }
inline void make_root(int x) { access(x);Splay(x); }
inline void link(int x,int y) { tree[x].fa=y;make_root(y);add(y,tree[x].sum); }
inline void cut(int x) { make_root(x);add(tree[x].ch[0],-tree[x].sum);tree[tree[x].ch[0]].fa=0;tree[x].ch[0]=0; }
struct sam
{int p,q,np,nq,cnt;int a[MAXN][3],fa[MAXN],len[MAXN];sam() { ++cnt; }inline int insert(int c,int last){p=last;np=++cnt;len[np]=len[p]+1;tree[np].sum=1;while (!a[p][c]&&p) a[p][c]=np,p=fa[p];if (!p) fa[np]=1,link(np,1),ans+=len[np]-len[1];else{q=a[p][c];if (len[q]==len[p]+1) fa[np]=q,link(np,q),ans+=len[np]-len[q];else{ans-=len[q]-len[fa[q]];nq=++cnt;len[nq]=len[p]+1;memcpy(a[nq],a[q],sizeof(a[q]));fa[nq]=fa[q];link(nq,fa[nq]);fa[q]=fa[np]=nq;cut(q);link(q,nq);link(np,nq);ans+=len[nq]-len[fa[nq]];ans+=len[q]-len[nq];ans+=len[np]-len[nq];while (a[p][c]==q) a[p][c]=nq,p=fa[p];}}return np;}
}sam;
void dfs(int x)
{vis[x]=1;for (edge *i=prev[x];i;i=i->next) if (!vis[i->to]) num[i->to]=sam.insert(i->w,num[x]),dfs(i->to);
}
int main()
{freopen("data2.in","r",stdin);freopen("data2.out","w",stdout);in(n);in(n);int opt,rt,sz,u,v;char c;for (int i=1;i<n;i++){in(u);in(v);c=' ';while (c<'a'||c>'c') c=getchar();insert(u,v,c-'a');insert(v,u,c-'a');}num[1]=1;dfs(1);for (in(m);m;m--){in(opt);if (opt==1) printf("%I64d\n",ans);if (opt==2){in(rt);in(sz);for (int i=1;i<sz;i++){in(u);in(v);c=' ';while (c<'a'||c>'c') c=getchar();insert(u,v,c-'a');insert(v,u,c-'a');}dfs(rt);}if (opt==3){scanf("%s",s+1);int l=strlen(s+1),now=1;for (int i=1;now&&i<=l;i++) now=sam.a[now][s[i]-'a'];if (!now) puts("0");else Splay(now),printf("%d\n",tree[now].sum);}}
}
【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条边,每条边上有一个字符 ...
- BZOJ3166 [Heoi2013]Alo 【可持久化trie树 + 二分 + ST表】
题目 Welcome to ALO ( Arithmetic and Logistic Online).这是一个VR MMORPG , 如名字所见,到处充满了数学的谜题. 现在你拥有n颗宝石,每颗宝石 ...
- usaco Cowxor (trie 树)
没想到trie树还可以用在这上面,厉害厉害. [分析]这是字母树的经典应用.首先因为是求xor的最大值,可以用前缀和计算xor值,然后n^2枚举即可. [cpp] view plaincopy for ...
- 字符串匹配算法 -- AC自动机 基于Trie树的高效的敏感词过滤算法
文章目录 1. 算法背景 2. AC自动机实现原理 2.1 构建失败指针 2.2 依赖失败指针过滤敏感词 3. 复杂度及完整代码 1. 算法背景 之前介绍过单模式串匹配的高效算法:BM和KMP 以及 ...
- 字符串匹配数据结构 --Trie树 高效实现搜索词提示 / IDE自动补全
文章目录 1. 算法背景 2. Trie 树实现原理 2.1 Trie 树的构建 2.2 Trie树的查找 2.3 Trie树的遍历 2.4 Trie树的时间/空间复杂度 2.5 Trie 树 Vs ...
- POJ 2418 Hardwood Species(trie 树)
题目链接 开始想用map的,字典序不会搞,还是老老实实的用trie树把.好久没写了,忘得差不多了. 1 #include <iostream> 2 #include <cstdio& ...
- Kanade's trio 2017多校#3 trie
求数组中i<j<k 并且ai^aj<aj^ak的三元组组数 枚举插入ak,让ak中每一位作为最高位,查找字典树内最高位不同的数字数量 注意把ak的每个前缀做一个bad标记 存储让这个 ...
- [您有新的未分配科技点]可,可,可持久化!?------0-1Trie和可持久化Trie普及版讲解...
这一次,我们来了解普通Trie树的变种:0-1Trie以及在其基础上产生的可持久化Trie(其实,普通的Trie也可以可持久化,只是不太常见) 先简单介绍一下0-1Trie:一个0-1Trie节点只有 ...
最新文章
- 微型计算机一般按字长进行分类,关于计算机中:字,字节,字长,位的关系
- js鼠标按键事件和键盘按键事件用法实例汇总
- 屏幕坏点怎么产生的_修复液晶屏幕坏点的妙招
- element UI 制作带快捷选项的时间选择器
- ios nslog 例子_iOS Block实例
- vue项目封装axios请求
- 【转】SharePoint Content Database简介
- 安装、部署DPM 2012 R2服务器
- Linux 下 I/O 多路复用技术 epoll
- 算数平均法和加权平均法
- 实在抵不住张老师的诱惑,又跳坑了
- 无法显示 隐藏文件 无法启动 杀毒软件 svohost exe CheckedValue Dword
- HTTP常用状态码状态码大全
- win10 android 共享文件,手把手教您win10系统通过局域网共享文件的解决方案
- Matlab转置transpose, .‘与复共轭转置ctranspose, ‘
- 关于element-ui的分页器设置每一页显示数量(page-size)后页码并没有变化的问题与解决
- ADSL拨号中出现的错误代码含义
- 当成为全球第二大汽车出口国后,中国车企的下一步是什么?
- 遥感影像出现nan如何处理、envi主成分分析nan报错处理
- SAAS模式的电商ERP有哪些好处?