Description

懒得写背景了,给你一个字符串init,要求你支持两个操作
(1):在当前字符串的后面插入一个字符串
(2):询问字符串s在当前字符串中出现了几次?(作为连续子串)
你必须在线支持这些操作。

Input

第一行一个数Q表示操作个数
第二行一个字符串表示初始字符串init
接下来Q行,每行2个字符串Type,Str
Type是ADD的话表示在后面插入字符串。
Type是QUERY的话表示询问某字符串在当前字符串中出现了几次。
为了体现在线操作,你需要维护一个变量mask,初始值为0 

读入串Str之后,使用这个过程将之解码成真正询问的串TrueStr。
询问的时候,对TrueStr询问后输出一行答案Result
然后mask=maskxorResult
插入的时候,将TrueStr插到当前字符串后面即可。
HINT:ADD和QUERY操作的字符串都需要解压
长度 <= 600000,询问次数<= 10000,询问总长度<= 3000000
新加数据一组--2015.05.20

Output

 

Sample Input

2
A
QUERY B
ADD BBABBBBAAB

Sample Output

0

解题思路:

从后缀自动机构造的时候入手,因为Parent树是与pre指针直接相关,就在pre指针构造的时候快速维护Parent(LCT)。
剩下的就是两个模板堆叠,没什么思维含量。

代码:

 #include<cstdio>
#include<cstring>
#include<algorithm>
#define lll tr[spc].ch[0]
#define rrr tr[spc].ch[1]
#define ls ch[0]
#define rs ch[1]
class Unzip{
public:
void update(int lastans)
{
mask^=lastans;
return ;
}
void decode(int *a,int len)
{
int upg=mask;
for(int i=;i<=len;i++)
tmp[i-]=a[i];
for(int i=;i<len;i++)
{
upg=(upg*+i)%len;
std::swap(tmp[i],tmp[upg]);
}
for(int i=;i<=len;i++)
a[i]=tmp[i-];
return ;
}
private:
int tmp[];
int mask;
}U;
struct trnt{
int ch[];
int fa;
int is;
int lzt;
int wgt;
int wgti;
bool anc;
}tr[];
struct sant{
int tranc[];
int len;
int pre;
}s[];
int Q;
int siz;
int fin;
int lasans;
char tmp[];
int atp[];
bool whc(int spc)
{
return tr[tr[spc].fa].rs==spc;
}
void pushup(int spc)
{
tr[spc].wgt=tr[spc].wgti+tr[spc].is+tr[lll].wgt+tr[rrr].wgt;
return ;
}
void trr(int spc)
{
if(!spc)
return ;
std::swap(lll,rrr);
tr[spc].lzt^=;
return ;
}
void pushdown(int spc)
{
if(tr[spc].lzt)
{
trr(lll);
trr(rrr);
tr[spc].lzt=;
}
return ;
}
void recal(int spc)
{
if(!tr[spc].anc)
recal(tr[spc].fa);
pushdown(spc);
return ;
}
void rotate(int spc)
{
int f=tr[spc].fa;
bool k=whc(spc);
tr[f].ch[k]=tr[spc].ch[!k];
tr[spc].ch[!k]=f;
if(tr[f].anc)
{
tr[f].anc=;
tr[spc].anc=;
}else
tr[tr[f].fa].ch[whc(f)]=spc;
tr[spc].fa=tr[f].fa;
tr[f].fa=spc;
tr[tr[f].ch[k]].fa=f;
pushup(f);
pushup(spc);
return ;
}
void splay(int spc)
{
recal(spc);
while(!tr[spc].anc)
{
int f=tr[spc].fa;
if(tr[f].anc)
{
rotate(spc);
return ;
}
if(whc(spc)^whc(f))
rotate(spc);
else
rotate(f);
rotate(spc);
}
return ;
}
void access(int spc)
{
int lst=;
while(spc)
{
splay(spc);
tr[spc].wgti-=tr[lst].wgt;
tr[spc].wgti+=tr[rrr].wgt;
tr[rrr].anc=;
tr[lst].anc=;
rrr=lst;
pushup(spc);
lst=spc;
spc=tr[spc].fa;
}
return ;
}
void Mtr(int spc)
{
access(spc);
splay(spc);
trr(spc);
return ;
}
void split(int x,int y)
{
Mtr(x);
access(y);
splay(y);
return ;
}
void link(int x,int y)
{
split(x,y);
tr[x].fa=y;
tr[y].wgti+=tr[x].wgt;
pushup(y);
return ;
}
void cut(int x,int y)
{
split(x,y);
tr[x].fa=;
tr[y].ls=;
tr[x].anc=;
pushup(y);
return ;
}
void Insert(int c)
{
int nwp,nwq,lsp,lsq;
nwp=++siz;
tr[nwp].anc=;
tr[nwp].is=;
s[nwp].len=s[fin].len+;
for(lsp=fin;lsp&&!s[lsp].tranc[c];lsp=s[lsp].pre)
s[lsp].tranc[c]=nwp;
if(!lsp)
{
s[nwp].pre=;
link(nwp,);
}else{
lsq=s[lsp].tranc[c];
if(s[lsq].len==s[lsp].len+)
{
s[nwp].pre=lsq;
link(nwp,lsq);
}else{
nwq=++siz;
tr[nwq].anc=;
s[nwq]=s[lsq];
cut(s[lsq].pre,lsq);
link(s[nwq].pre,nwq);
s[nwq].len=s[lsp].len+;
s[nwp].pre=s[lsq].pre=nwq;
link(nwq,nwp);
link(nwq,lsq);
while(s[lsp].tranc[c]==lsq)
{
s[lsp].tranc[c]=nwq;
lsp=s[lsp].pre;
}
}
}
fin=nwp;
return ;
}
int Query(int root)
{
Mtr();
access(root);
return tr[root].wgti+tr[root].is;
}
int main()
{
fin=++siz;
tr[fin].anc=;
scanf("%d",&Q);
scanf("%s",tmp+);
int len=strlen(tmp+);
for(int i=;i<=len;i++)
Insert(tmp[i]-'A');
while(Q--)
{
scanf("%s",tmp);
if(tmp[]=='A')
{
scanf("%s",tmp+);
len=strlen(tmp+);
for(int i=;i<=len;i++)
atp[i]=tmp[i]-'A';
U.decode(atp,len);
for(int i=;i<=len;i++)
Insert(atp[i]);
}else{
scanf("%s",tmp+);
len=strlen(tmp+);
for(int i=;i<=len;i++)
atp[i]=tmp[i]-'A';
U.decode(atp,len);
int root=;
for(int i=;i<=len;i++)
{
root=s[root].tranc[atp[i]]; }
if(!root)
lasans=;
else
lasans=Query(root);
printf("%d\n",lasans);
U.update(lasans);
}
}
return ;
}

BZOJ2555: SubString(后缀自动机,LCT维护Parent树)的更多相关文章

  1. bzoj 2555 SubString —— 后缀自动机+LCT

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2555 建立后缀自动机,就可以直接加入新串了: 出现次数就是 Right 集合的大小,需要查询 ...

  2. luogu5212/bzoj2555 substring(后缀自动机+动态树)

    对字符串构建一个后缀自动机. 每次查询的就是在转移边上得到节点的parent树中后缀节点数量. 由于强制在线,可以用动态树维护后缀自动机parent树的子树和. 注意一个玄学的优化:每次在执行连边操作 ...

  3. 【BZOJ2555】SubString 后缀自动机+LCT

    [BZOJ2555]SubString Description 懒得写背景了,给你一个字符串init,要求你支持两个操作         (1):在当前字符串的后面插入一个字符串         (2 ...

  4. [Bzoj3676][Apio2014]回文串(后缀自动机)(parent树)(倍增)

    3676: [Apio2014]回文串 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 3396  Solved: 1568[Submit][Statu ...

  5. bzoj 3881 [Coci2015]Divljak——LCT维护parent树链并

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3881 对 S 建 SAM ,每个 T 会让 S 的 parent 树的链并答案+1:在 T ...

  6. bzoj 2555: SubString 后缀自动机+LCT

    2555: SubString Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 688  Solved: 235[Submit][Status][Dis ...

  7. bzoj 2555 SubString——后缀自动机+LCT

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2555 要维护 right 集合的大小.因为 fa 会变,且 fa 构成一棵树,所以考虑用 L ...

  8. BZOJ2555 SubString 【后缀自动机 + LCT】

    题目 懒得写背景了,给你一个字符串init,要求你支持两个操作 (1):在当前字符串的后面插入一个字符串 (2):询问字符串s在当前字符串中出现了几次?(作为连续子串) 你必须在线支持这些操作. 输入 ...

  9. BZOJ2555 SubString(后缀自动机+LCT)

    询问串放在SAM上不跳fail跑到的节点的|right|即为答案.用LCT维护parent树即可.可以直接维护子树信息,也可以转化为路径加.注意强制在线所使用的mask是作为参数传进去的. #incl ...

随机推荐

  1. openCV 和GDI画线效率对照

    一. 因为项目须要,原来用GDI做的画线的功能.新的项目中考虑到垮平台的问题.打算用openCV来实现.故此做个效率对照. 二. 2点做一条线,来測试效率. 用了相同的画板大小---256*256的大 ...

  2. vim插件之delimitMate.vim

    delimitMate.vim--这个插件主要是在插入模式下,用来自动补全括号.引号等 下载地址 http://www.vim.org/scripts/script.php?script_id=275 ...

  3. Firefox访问https的网站,一直提示不安全

    http://mozilla.com.cn/thread-374897-1-1.html 要激活此功能步骤如下: 在地址栏键入"about:config" 点击“我了解此风险” 在 ...

  4. 面向对象 —— 对类(class)的理解

    类是成员变量和成员函数的封装,封装的一个重要功能就是可见性(继承除外,当然继承是面向对象的另外一个重要特性),所谓可见性,类内可见,类外不可见.可见性保证了类型安全(type-safe) 对类进行实例 ...

  5. 104.virtual虚函数多态与异构数据结构

    #include "mainwindow.h" #include <QApplication> #include <list> #include <Q ...

  6. UESTC 1584

    http://acm.uestc.edu.cn/#/problem/show/1584 Washi与Sonochi的约定 Time Limit: 3000/1000MS (Java/Others)   ...

  7. TI Code Composer Studio MSP430系列驱动源代码

    一.参考TI官网驱动源代码 安装打开Code Composer Studio,如下图所示,最近在调试MSP430G2533的AD,需要参考官网的底层驱动配置. 从Code Composer Studi ...

  8. DB2物化视图(Materialized Query Tables, MQT)

    DB2的物化视图MQT是基于查询结果定义的一个表,MQT中包括的数据来自MQT定义所基于的一个或多个表, 使用MQT能够显著提高查询的操作性能. 数据库的视图和MQT都是基于一个查询来定义的.每当视图 ...

  9. php intval函数

    php intval函数 作用 intval — 获取变量的整数值 使用实例 <?php echo intval('-42'); // -42 ?> 相似函数 boolval() - 获取 ...

  10. C#使用一般处理程序(ashx)中session

    .ashx中引用 session必须 using System.Web.SessionState ,继承IReadOnlySessionState/IRequiresSessionState IRea ...