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

Sample Input

2

A

QUERY B

ADD BBABBBBAAB

Sample Output

0

Solution

LCT+SAM

考虑静态时,一个字符串 \(S\) 在另一个字符串 \(T\) 中的出现次数。将 \(T\) 建出SAM,那么 \(S\) 出现次数就是先将 \(S\) 在SAM上匹配,然后匹配完的那个节点的size就是出现次数了。

那么动态的的话,用LCT维护parent树就好了

#include<bits/stdc++.h>
#define ui unsigned int
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
const int MAXN=600000+10,MAXM=3000000+10;
int n,q,ch[MAXN<<1][30],fa[MAXN<<1],len[MAXN<<1],size[MAXN<<1],mask,las=1,tot=1;
char s[MAXM];
#define lc(x) ch[(x)][0]
#define rc(x) ch[(x)][1]
struct LinkCut_Tree{
int sum[MAXN<<1],ch[MAXN<<1][2],fa[MAXN<<1],stack[MAXN<<1],cnt,Isum[MAXN<<1],rev[MAXN<<1];
inline bool nroot(int x)
{
return lc(fa[x])==x||rc(fa[x])==x;
}
inline void reverse(int x)
{
std::swap(lc(x),rc(x));
rev[x]^=1;
}
inline void pushup(int x)
{
sum[x]=sum[lc(x)]+sum[rc(x)]+size[x]+Isum[x];
}
inline void pushdown(int x)
{
if(rev[x])
{
if(lc(x))reverse(lc(x));
if(rc(x))reverse(rc(x));
rev[x]=0;
}
}
inline void rotate(int x)
{
int f=fa[x],p=fa[f],c=(rc(f)==x);
if(nroot(f))ch[p][rc(p)==f]=x;
fa[ch[f][c]=ch[x][c^1]]=f;
fa[ch[x][c^1]=f]=x;
fa[x]=p;
pushup(f);
pushup(x);
}
inline void splay(int x)
{
cnt=0;
stack[++cnt]=x;
for(register int i=x;nroot(i);i=fa[i])stack[++cnt]=fa[i];
while(cnt)pushdown(stack[cnt--]);
for(register int y=fa[x];nroot(x);rotate(x),y=fa[x])
if(nroot(y))rotate((lc(y)==x)==(lc(fa[y])==y)?y:x);
pushup(x);
}
inline void access(int x)
{
for(register int y=0;x;x=fa[y=x])
{
splay(x);
Isum[x]+=sum[rc(x)];
rc(x)=y;
Isum[x]-=sum[rc(x)];
pushup(x);
}
}
inline void makeroot(int x)
{
access(x);splay(x);reverse(x);
}
inline void split(int x,int y)
{
makeroot(x);access(y);splay(y);
}
inline void link(int x,int y)
{
makeroot(x);access(y);splay(y);
fa[x]=y;
Isum[y]+=sum[x];
pushup(y);
}
inline void cut(int x,int y)
{
split(x,y);
fa[x]=lc(y)=0;
pushup(y);
}
};
LinkCut_Tree T;
#undef lc
#undef rc
template<typename T> inline void read(T &x)
{
T data=0,w=1;
char ch=0;
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
x=data*w;
}
template<typename T> inline void write(T x,char ch='\0')
{
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+'0');
if(ch!='\0')putchar(ch);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
inline void extend(int c)
{
int p=las,np=++tot;
las=np;
len[np]=len[p]+1;size[np]=1;
while(p&&!ch[p][c])ch[p][c]=np,p=fa[p];
if(!p)fa[np]=1,T.link(np,1);
else
{
int q=ch[p][c];
if(len[q]==len[p]+1)fa[np]=q,T.link(np,q);
else
{
int nq=++tot;
fa[nq]=fa[q];T.link(nq,fa[q]);
memcpy(ch[nq],ch[q],sizeof(ch[nq]));
len[nq]=len[p]+1;T.cut(q,fa[q]);
fa[q]=fa[np]=nq;T.link(q,nq);T.link(np,nq);
while(p&&ch[p][c]==q)ch[p][c]=nq,p=fa[p];
}
}
}
inline void decode(int mask)
{
for(register int i=0,lt=strlen(s);i<lt;++i)std::swap(s[i],s[mask=(mask*131+i)%lt]);
}
int main()
{
read(q);
scanf("%s",s);
for(register int i=0,lt=strlen(s);i<lt;++i)extend(s[i]-'A'+1);
while(q--)
{
char opt[8];scanf("%s",opt);scanf("%s",s);
decode(mask);
if(opt[0]=='A')
for(register int i=0,lt=strlen(s);i<lt;++i)extend(s[i]-'A'+1);
if(opt[0]=='Q')
{
int j=1,mark=1;
for(register int i=0,lt=strlen(s),c;i<lt;++i)
{
c=s[i]-'A'+1;
if(ch[j][c])j=ch[j][c];
else {mark=0;break;}
}
if(!mark)puts("0");
else
{
T.makeroot(1);T.access(j);
write(T.Isum[j]+size[j],'\n');
mask^=(T.Isum[j]+size[j]);
}
}
}
return 0;
}

【刷题】BZOJ 2555 SubString的更多相关文章

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

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

  2. 字符串(LCT,后缀自动机):BZOJ 2555 SubString

    2555: SubString Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 1620  Solved: 471 Description 懒得写背景了 ...

  3. ●BZOJ 2555 SubString

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=2555题解: 后缀自动机+LCT 不难发现,对于输入的询问串,在自动机里trans后的到的状态 ...

  4. bzoj 2555 SubString(SAM+LCT)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2555 [题意] 给定一个字符串,可以随时插入字符串,提供查询s在其中作为连续子串的出现 ...

  5. bzoj 2555: SubString

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

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

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

  7. 【leetcode刷题笔记】Substring with Concatenation of All Words

    You are given a string, S, and a list of words, L, that are all of the same length. Find all startin ...

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

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

  9. BZOJ 2555 SubString(LCT+后缀树)

    喜闻乐见的LCT+SAM 此题要求动态插入,直接上后缀树.然后询问其实就是求一个节点的子树后缀结束节点的个数. 因为建立后缀树需要插入和删除,就直接上LCT.每次加入一个点,把它到根的路径加一 (现在 ...

随机推荐

  1. KVM虚拟化的安装

    kvm介绍 一.KVM的历史 Kvm在2007年2月正式合并Linux2.6.20核心中,成为内核源代码的一部分.2008年9月4日,RedHat公司收购了Qumranet,开始在RHEL中用kvm取 ...

  2. LVS入门篇(五)之LVS+Keepalived实战

    一.实验架构和环境说明 (1)本次基于VMware Workstation搭建一个四台Linux(CentOS 7.4)系统所构成的一个服务器集群,其中两台负载均衡服务器(一台为主机,另一台为备机), ...

  3. 前端 CDNJS 库及 Google Fonts、Ajax 和 Gravatar 国内加速服务

    由于某些众所周知的原因,好多开源的 JS 库采用的国外 CDN 托管方式在国内访问速度不如人意.所以我们特意制作了这个公益项目,托管了 CDNJS 的所有开源 JS 库以及反代了 Google Fon ...

  4. 问题:python2.7 安装包失败,提示错误:Microsoft Visual C++ 9.0 is required (Unable to find vcvarsall.bat)

    问题描述: 使用pip安装包时报错,error: Microsoft Visual C++ 9.0 is required (Unable to find vcvarsall.bat) 环境: pyt ...

  5. python常用模块详解2

    序列化模块补充: 1.json格式的限制,json格式的key必须是字符串数据类型 2.json格式的字符串必须是"" 如果数字是key,那么dump之后会强转成字符串数据类型 i ...

  6. 面向英特尔® x86 平台的 Unity* 优化指南: 第 1 部分

    原文地址 目录 工具 Unity 分析器 GPA 系统分析器 GPA 帧分析器 如要充分发挥 x86 平台的作用,您可以在项目中进行多种性能优化,以最大限度地提升性能. 在本指南中,我们将展示 Uni ...

  7. No.03---Vue学习之路之模块化组织

    前两篇讲解了一下 Vuex 的基本使用方法,可是在实际项目中那么写肯定是不合理的,如果组件太多,不可能把所有组件的数据都放到一个 store.js 中的,所以就需要模块化的组织 Vuex,首先看一下 ...

  8. Paper Reading - Attention Is All You Need ( NIPS 2017 ) ★

    Link of the Paper: https://arxiv.org/abs/1706.03762 Motivation: The inherently sequential nature of ...

  9. leetcode个人题解——#40 Combination Sum2

    思路:解法和39题类似,改动了两处: 1.因为题目要求每个元素只能出现一次(不代表每个数只能有一个,因为数据中会有重复的数字),所以代码中21行搜索时下一次循环的位置+1: 2.将临时存放答案的vec ...

  10. 第一次ScrumMeeting博客:团队任务分解

    团队任务分解 1. 主要任务 Alpha阶段结束后,我们要实现一个较为简陋的用户系统,并实现资源的上传和下载功能,完成"贡献点"相关内容并进行用户行为观察,以便Beta阶段完善.除 ...