题意:
  (1):在当前字符串的后面插入一个字符串
  (2):询问字符串s在当前字符串中出现了几次?(作为连续子串)
  字符串长度<=6e5,询问总长度<=3e6
分析:
  考虑建个sam,然后把slink连起来就形成了一个前缀树
  对于每个询问的串,就是求出它在sam里对应的点,然后在slink树种该点子树的size就是答案
  用lct维护slink树即可
 #include<bits/stdc++.h>
using namespace std;
const int maxn=;
const int maxs=3e6; struct LCT
{
int ch[maxn+][],fa[maxn+],flip[maxn+];
int top;
int q[maxn+];
int sz[maxn+];
int tag[maxn+];
void init()
{ }
bool isroot(int x)
{
return ch[fa[x]][]!=x&&ch[fa[x]][]!=x;
}
void add(int x,int data)
{
if(x)
{
tag[x]+=data;
sz[x]+=data;
}
}
void pushdown(int x)
{
int l=ch[x][],r=ch[x][];
if(flip[x])
{
flip[x]^=;flip[l]^=;flip[r]^=;
swap(ch[x][],ch[x][]);
}
if(tag[x])
{
add(l,tag[x]),add(r,tag[x]);
tag[x]=;
}
}
void rotate(int &x)
{
int y=fa[x],z=fa[y],l,r;
if(ch[y][]==x) l=;
else l=;
r=l^;
if(!isroot(y))
{
if(ch[z][]==y) ch[z][]=x;
else ch[z][]=x;
}
fa[x]=z;fa[y]=x;fa[ch[x][r]]=y;
ch[y][l]=ch[x][r];ch[x][r]=y;
}
void splay(int &x)
{
top=;
q[++top]=x;
for(int i=x;!isroot(i);i=fa[i]) q[++top]=fa[i];
while(top) pushdown(q[top--]);
while(!isroot(x))
{
int y=fa[x],z=fa[y];
if(!isroot(y))
{
if(ch[y][]==x^ch[z][]==y) rotate(x);
else rotate(y);
}
rotate(x);
}
}
void access(int x)
{
for(int t=;x;t=x,x=fa[x])
splay(x),ch[x][]=t;
}
void link(int x,int f)
{
fa[x]=f;
access(f);
splay(f);
add(f,sz[x]);
}
void cut(int x)
{
access(x);
splay(x);
add(ch[x][],-sz[x]);
fa[ch[x][]]=,ch[x][]=;
}
int query(int x)
{
access(x);
splay(x);
return sz[x];
}
}lct; struct SAM
{
int maxlen[maxn+],minlen[maxn+],trans[maxn+][],slink[maxn+];
int sz,last;
void init()
{
for(int i=;i<;++i) trans[][i]=slink[]=-;
maxlen[]=minlen[]=;
sz=;
last=;
}
int build(int _maxlen,int _minlen,int* _trans,int _slink)
{
maxlen[++sz]=_maxlen;
minlen[sz]=_minlen;
for(int i=;i<;++i)
if(_trans==NULL) trans[sz][i]=-;else trans[sz][i]=_trans[i];
slink[sz]=_slink;
return sz;
}
int add(char ch,int u)
{
int c=ch-'A';
int z=build(maxlen[u]+,-,NULL,-);
lct.sz[z]=;
int v=u;
while(v!=-&&trans[v][c]==-)
{
trans[v][c]=z,v=slink[v];
}
if(v==-)//最简单的情况,suffix-path(u->S)上都没有对应字符ch的转移
{
minlen[z]=;
slink[z]=;
lct.link(z,);
return z;
}
int x=trans[v][c];
if(maxlen[v]+==maxlen[x])//较简单的情况,不用拆分x
{
minlen[z]=maxlen[x]+;
slink[z]=x;
lct.link(z,x);
return z;
}
int y=build(maxlen[v]+,-,trans[x],slink[x]); //最复杂的情况,拆分x,y表示<=maxlen[v]+1的那段
slink[y]=slink[x];
lct.link(y,slink[y]);
minlen[x]=maxlen[y]+;
lct.cut(x);
slink[x]=y;
lct.link(x,y);
minlen[z]=maxlen[y]+;
slink[z]=y;
lct.link(z,y);
int w=v;
while(w!=-&&trans[w][c]==x) trans[w][c]=y,w=slink[w];
minlen[y]=maxlen[slink[y]]+;
return z;
}
void append(char *s)
{
int len=strlen(s);
for(int i=;i<len;++i) last=add(s[i],last);
}
int query(char *s)
{
int len=strlen(s);
int now=;
for(int i=;i<len;++i)
{
now=trans[now][s[i]-'A'];
if(now==-) return ;
}
return lct.query(now);
}
}sam;
char s[maxs+];
int mask=;
void gets(int mask)
{
scanf("%s",s);
int len=strlen(s);
for (int j=;j<len;j++)
{
mask=(mask*+j)%len;
char t=s[j];
s[j]=s[mask];
s[mask]=t;
}
}
int main()
{
int q;
scanf("%d",&q);
sam.init();
scanf("%s",s);
sam.append(s);
while(q--)
{
scanf("%s",s);
if(s[]=='A')
{
gets(mask);
sam.append(s);
}
else
{
gets(mask);
int ans=sam.query(s);
mask^=ans;
printf("%d\n",ans);
}
}
return ;
}

bzoj2555(lct维护sam)的更多相关文章

  1. 【LOJ6041】「雅礼集训 2017 Day7」事情的相似度(用LCT维护SAM的parent树)

    点此看题面 大致题意: 给你一个\(01\)串,每次询问前缀编号在一段区间内的两个前缀的最长公共后缀的长度. 离线存储询问 考虑将询问离线,按右端点大小用邻接表存下来(直接排序当然也可以啦). 这样的 ...

  2. BZOJ2555 SubString【SAM + Link Cut Tree】

    BZOJ2555. SubString 要求在线询问一个串在原串中出现的次数,并且可以在原串末尾添加字符串 如果没有修改的话,考虑建出\(parent\)树之后统计每个\(endpos\)节点的\(r ...

  3. 【LCT维护基环内向树森林】BZOJ4764 弹飞大爷

    4764: 弹飞大爷 Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 101  Solved: 52[Submit][Status][Discuss] ...

  4. LCT维护子树信息(BZOJ4530:[BJOI2014]大融合)

    题面 没有权限号的可以去LOJ Sol 大家都知道,\(LCT\)上有许多实边和虚边 实边就是每棵\(Splay\)上的既认父亲又认儿子的边 虚边就是\(Splay\)和\(Splay\)之间只认父亲 ...

  5. 【bzoj4530】[Bjoi2014]大融合 LCT维护子树信息

    题目描述 小强要在N个孤立的星球上建立起一套通信系统.这套通信系统就是连接N个点的一个树. 这个树的边是一条一条添加上去的.在某个时刻,一条边的负载就是它所在的当前能够联通的树上路过它的简单路径的数量 ...

  6. BZOJ4530[Bjoi2014]大融合——LCT维护子树信息

    题目描述 小强要在N个孤立的星球上建立起一套通信系统.这套通信系统就是连接N个点的一个树. 这个树的边是一条一条添加上去的.在某个时刻,一条边的负载就是它所在的当前能够 联通的树上路过它的简单路径的数 ...

  7. LOJ 121 「离线可过」动态图连通性——LCT维护删除时间最大生成树 / 线段树分治

    题目:https://loj.ac/problem/121 离线,LCT维护删除时间最大生成树即可.注意没有被删的边的删除时间是 m+1 . 回收删掉的边的节点的话,空间就可以只开 n*2 了. #i ...

  8. LCT维护子树信息

    有些题目,在要求支持link-cut之外,还会在线询问某个子树的信息.LCT可以通过维护虚边信息完成这个操作. 对于LCT上每个节点,维护两个两sz和si,后者维护该点所有虚儿子的信息,前者维护该点的 ...

  9. 【uoj#207】共价大爷游长沙 随机化+LCT维护子树信息

    题目描述 给出一棵树和一个点对集合S,多次改变这棵树的形态.在集合中加入或删除点对,或询问集合内的每组点对之间的路径是否都经过某条给定边. 输入 输入的第一行包含一个整数 id,表示测试数据编号,如第 ...

随机推荐

  1. (转发)IOS高级开发~Runtime(一)

    IOS高级开发-Runtime(一) IOS高级开发-Runtime(二) IOS高级开发-Runtime(三) IOS高级开发-Runtime(四) 一些公用类: @interface Custom ...

  2. 新浪oAuth授权

    首先要拥有一个微博账号   第一步 成为新浪开发者 1.登录微博开发者界面 open.weibo.com 2. 点击登录 点击移动应用,创建应用   3.需要进行开发者认证,填写个人信息及邮箱认证,等 ...

  3. (27)zabbix自定义图表Graph

    zabbix提供了一个自定义图表的功能,这不是废话么?呵呵~前面文章 讲到的<zabbix简易图表>只能显示单个item的数据图表.如果我们想显示多个信息到一个图表上,那必须使用zabbi ...

  4. 【git】不检查特定文件的更改情况

    .gitignore只能忽略那些原来没有被track的文件,如果某些文件已经被纳入了版本管理中,则修改.gitignore是无效的.正确的做法是在每个clone下来的仓库中手动设置不要检查特定文件的更 ...

  5. python学习第一天 计算机基础知识

    目录 什么是编程语言 什么是编程? 为什么要编程? 计算机5大组成分别有什么作用? qq启动的流程? 建议相关学习 课外 什么是编程语言 什么是编程语言? python和中文.英语一样,都是一门语言, ...

  6. 20181121笔记(for,数字类型和字符串类型的内置方法)

    1.for循环 for循环可以遍历任何序列的项目,如一个列表或者一个字符串. for循环字典时默认取出key: dic={'x':111,'y':222,'z:333'}​for k in dic:​ ...

  7. (转)5个Xcode开发调试技巧

    1.Enable NSZombie Objects(开启僵尸对象) Enable NSZombie Objects可能是整个Xcode开发环境中最有用的调试技巧.这个技巧非常非常容易追踪到重复释放的问 ...

  8. linux文本界面../和./的区别

    linux文本界面../和./的区别 ../代表的是上一个目录 ./代表的当前目录

  9. Python中正则表达式讲解

    正则表达式是匹配字符串的强大武器,它的核心思想是给字符串定义规则,凡是符合规则的字符串就是匹配了,否则就是不合法的.在介绍Python的用法之前,我们先讲解一下正则表达式的规则,然后再介绍在Pytho ...

  10. PAT Basic 1022

    1022 D进制的A+B 输入两个非负10进制整数A和B(<=2^30^-1),输出A+B的D (1 < D <= 10)进制数. 输入格式: 输入在一行中依次给出3个整数A.B和D ...