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相关推荐

  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. BZOJ3166 [Heoi2013]Alo 【可持久化trie树 + 二分 + ST表】

    题目 Welcome to ALO ( Arithmetic and Logistic Online).这是一个VR MMORPG , 如名字所见,到处充满了数学的谜题. 现在你拥有n颗宝石,每颗宝石 ...

  4. usaco Cowxor (trie 树)

    没想到trie树还可以用在这上面,厉害厉害. [分析]这是字母树的经典应用.首先因为是求xor的最大值,可以用前缀和计算xor值,然后n^2枚举即可. [cpp] view plaincopy for ...

  5. 字符串匹配算法 -- AC自动机 基于Trie树的高效的敏感词过滤算法

    文章目录 1. 算法背景 2. AC自动机实现原理 2.1 构建失败指针 2.2 依赖失败指针过滤敏感词 3. 复杂度及完整代码 1. 算法背景 之前介绍过单模式串匹配的高效算法:BM和KMP 以及 ...

  6. 字符串匹配数据结构 --Trie树 高效实现搜索词提示 / IDE自动补全

    文章目录 1. 算法背景 2. Trie 树实现原理 2.1 Trie 树的构建 2.2 Trie树的查找 2.3 Trie树的遍历 2.4 Trie树的时间/空间复杂度 2.5 Trie 树 Vs ...

  7. POJ 2418 Hardwood Species(trie 树)

    题目链接 开始想用map的,字典序不会搞,还是老老实实的用trie树把.好久没写了,忘得差不多了. 1 #include <iostream> 2 #include <cstdio& ...

  8. Kanade's trio 2017多校#3 trie

    求数组中i<j<k 并且ai^aj<aj^ak的三元组组数 枚举插入ak,让ak中每一位作为最高位,查找字典树内最高位不同的数字数量 注意把ak的每个前缀做一个bad标记 存储让这个 ...

  9. [您有新的未分配科技点]可,可,可持久化!?------0-1Trie和可持久化Trie普及版讲解...

    这一次,我们来了解普通Trie树的变种:0-1Trie以及在其基础上产生的可持久化Trie(其实,普通的Trie也可以可持久化,只是不太常见) 先简单介绍一下0-1Trie:一个0-1Trie节点只有 ...

最新文章

  1. 微型计算机一般按字长进行分类,关于计算机中:字,字节,字长,位的关系
  2. js鼠标按键事件和键盘按键事件用法实例汇总
  3. 屏幕坏点怎么产生的_修复液晶屏幕坏点的妙招
  4. element UI 制作带快捷选项的时间选择器
  5. ios nslog 例子_iOS Block实例
  6. vue项目封装axios请求
  7. 【转】SharePoint Content Database简介
  8. 安装、部署DPM 2012 R2服务器
  9. Linux 下 I/O 多路复用技术 epoll
  10. 算数平均法和加权平均法
  11. 实在抵不住张老师的诱惑,又跳坑了
  12. 无法显示 隐藏文件 无法启动 杀毒软件 svohost exe CheckedValue Dword
  13. HTTP常用状态码状态码大全
  14. win10 android 共享文件,手把手教您win10系统通过局域网共享文件的解决方案
  15. Matlab转置transpose, .‘与复共轭转置ctranspose, ‘
  16. 关于element-ui的分页器设置每一页显示数量(page-size)后页码并没有变化的问题与解决
  17. ADSL拨号中出现的错误代码含义
  18. 当成为全球第二大汽车出口国后,中国车企的下一步是什么?
  19. 遥感影像出现nan如何处理、envi主成分分析nan报错处理
  20. SAAS模式的电商ERP有哪些好处?

热门文章

  1. 数据库设计第一范式(1NF)
  2. 【软件测试基本流程】
  3. hdfs命令响应特别慢的问题
  4. opencv-python简易文档(三)图像处理算法
  5. 黑客借由入侵WordPress网站,使造访者计算机被植入恶意的Chrome扩充程序
  6. 用python绘制心形_python绘制心形图像-Go语言中文社区
  7. MySQL数据库面试题(50道题含答案和思维导图总结)
  8. 【VPR】 Command-line - vpr的命令行选项(一)
  9. 解决黑群晖故障-抱歉,您所指定的页面不存在
  10. Oracle数据库安装,以及使用plsql Dev连接数据库实例