BZOJ2555 SubString【后缀自动机+LCT】
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
思路
用LCT来维护prt树的链接关系
直接在extend的时候维护关系就可以了
注意o节点要和先前的节点断开关系
然后顺便维护siz集合的大小就可以了
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define fu(a,b,c) for(int a=b;a<=c;++a)
#define fd(a,b,c) for(int a=b;a>=c;--a)
#define N 6000010
//Link_Cut_Tree
struct Splay{
Splay *fa,*ch[2];
int siz,add;
}_null,*null=&_null;
Splay *newnode(int vl=0){
Splay *t=new Splay;
t->siz=vl;
t->fa=t->ch[1]=t->ch[0]=null;
return t;
}
bool son(Splay *t){return t->fa->ch[1]==t;}
bool isroot(Splay *t){return t->fa->ch[0]!=t&&t->fa->ch[1]!=t;}
void pushnow(Splay *x,int vl){x->add+=vl;x->siz+=vl;}
void pushdown(Splay *t){
if(!isroot(t))pushdown(t->fa);
if(t->add){
if(t->ch[0]!=null)pushnow(t->ch[0],t->add);
if(t->ch[1]!=null)pushnow(t->ch[1],t->add);
t->add=0;
}
}
void rotate(Splay *t){
Splay *f=t->fa,*g=f->fa;
bool a=son(t),b=a^1;
if(!isroot(f))g->ch[son(f)]=t;
t->fa=g;
f->ch[a]=t->ch[b];t->ch[b]->fa=f;
t->ch[b]=f;f->fa=t;
}
void splay(Splay *t){
pushdown(t);
while(!isroot(t)){
Splay *f=t->fa;
if(!isroot(f)){
if(son(t)^son(f))rotate(t);
else rotate(f);
}
rotate(t);
}
}
void access(Splay *t){
Splay *tmp=null;
while(t!=null){
splay(t);
t->ch[1]=tmp;
tmp=t;t=t->fa;
}
}
void link(Splay *x,Splay *y){
access(y);
splay(y);
x->fa=y;
pushnow(y,x->siz);
}
void cut(Splay *x){
access(x);
splay(x);
pushnow(x->ch[0],-x->siz);
x->ch[0]->fa=null;
x->ch[0]=null;
}
//Suffix_Automaton
const int CHARSET_SIZE=26;
struct Sam{
Sam *ch[CHARSET_SIZE],*prt;
Splay *right;
int maxl;
Sam(int vl=0,int siz=0){
prt=NULL;
memset(ch,0,sizeof(ch));
maxl=vl;
right=newnode(siz);
}
}*root=new Sam,*last=root;
void extend(int c){
Sam *u=new Sam(last->maxl+1,1),*v=last;
for(;v&&!v->ch[c];v=v->prt)v->ch[c]=u;
if(!v){
u->prt=root;
link(u->right,root->right);
}else if(v->maxl+1==v->ch[c]->maxl){
u->prt=v->ch[c];
link(u->right,v->ch[c]->right);
}else{
Sam *n=new Sam(v->maxl+1,0),*o=v->ch[c];
copy(o->ch,o->ch+CHARSET_SIZE,n->ch);
n->prt=o->prt;
link(n->right,o->prt->right);
o->prt=u->prt=n;
cut(o->right);
link(o->right,n->right);
link(u->right,n->right);
for(;v&&v->ch[c]==o;v=v->prt)v->ch[c]=n;
}
last=u;
}
//solve and main
char s[N],op[10];
int len,mask=0;
void decode(int m){
fu(i,0,len-1){
m=(m*131+i)%len;
swap(s[i],s[m]);
}
}
int main(){
//freopen("input.txt","r",stdin);
int q;scanf("%d",&q);
scanf("%s",s);
len=strlen(s);
fu(i,0,len-1)extend(s[i]-'A');
while(q--){
scanf("%s %s",op,s);
len=strlen(s);
decode(mask);
if(op[0]=='Q'){
Sam *now=root;
int can=1;
fu(i,0,len-1){
int c=s[i]-'A';
if(!now->ch[c]){can=0;break;}
now=now->ch[c];
}
if(!can){printf("0\n");continue;}
splay(now->right);
mask^=now->right->siz;
printf("%d\n",now->right->siz);
}else fu(i,0,len-1)extend(s[i]-'A');
}
return 0;
}
BZOJ2555 SubString【后缀自动机+LCT】的更多相关文章
- luogu5212/bzoj2555 substring(后缀自动机+动态树)
对字符串构建一个后缀自动机. 每次查询的就是在转移边上得到节点的parent树中后缀节点数量. 由于强制在线,可以用动态树维护后缀自动机parent树的子树和. 注意一个玄学的优化:每次在执行连边操作 ...
- bzoj 2555 SubString —— 后缀自动机+LCT
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2555 建立后缀自动机,就可以直接加入新串了: 出现次数就是 Right 集合的大小,需要查询 ...
- 【BZOJ2555】SubString 后缀自动机+LCT
[BZOJ2555]SubString Description 懒得写背景了,给你一个字符串init,要求你支持两个操作 (1):在当前字符串的后面插入一个字符串 (2 ...
- bzoj 2555: SubString 后缀自动机+LCT
2555: SubString Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 688 Solved: 235[Submit][Status][Dis ...
- bzoj 2555 SubString——后缀自动机+LCT
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2555 要维护 right 集合的大小.因为 fa 会变,且 fa 构成一棵树,所以考虑用 L ...
- BZOJ2555 SubString 【后缀自动机 + LCT】
题目 懒得写背景了,给你一个字符串init,要求你支持两个操作 (1):在当前字符串的后面插入一个字符串 (2):询问字符串s在当前字符串中出现了几次?(作为连续子串) 你必须在线支持这些操作. 输入 ...
- bzoj2555(后缀自动机+LCT)
题目描述 (1):在当前字符串的后面插入一个字符串 (2):询问字符串s在当前字符串中出现了几次?(作为连续子串) 你必须在线支持这些操作. 题解 做法很自然,建出后缀自动机,维护每个节点的right ...
- bzoj 2555: SubString【后缀自动机+LCT】
一直WA--找了半天错的发现居然是解密那里的mask其实是不能动的--传进去的会变,但是真实的那个不会变-- 然后就是后缀自动机,用LCT维护parent树了--注意不能makeroot,因为自动机的 ...
- SPOJ1811 LCS - Longest Common Substring(后缀自动机)
A string is finite sequence of characters over a non-empty finite set Σ. In this problem, Σ is the s ...
- 51nod 1600 Simple KMP【后缀自动机+LCT】【思维好题】*
Description 对于一个字符串|S|,我们定义fail[i],表示最大的x使得S[1..x]=S[i-x+1..i],满足(x<i) 显然对于一个字符串,如果我们将每个0<=i&l ...
随机推荐
- java中函数传值与引用问题
从C++转java,在使用函数传对象时,碰到一点问题,今天特意验证了一下: public class App { public static void doubleTest(double d) { d ...
- Memcached CAS 命令
Memcached CAS(Check-And-Set 或 Compare-And-Swap) 命令用于执行一个"检查并设置"的操作 它仅在当前客户端最后一次取值后,该key 对应 ...
- windows系统下,安装多个版本的jdk,java -version
问题描述: 开始安装了 jdk8 后来装了jdk9,可以为项目配置不同的jdk,相安无事: 今天发现软件需要jdk8的环境,结果我的java -version始终是jdk9.0.1: 解决办法:使ja ...
- spring mvc:练习:表单验证(javaConfig配置和注解)
使用Spring表单标签, 表单验证使用 JSR303 的验证注解,hibernate-validators,提供了使用MessageSource和访问静态资源(如CSS,JavaScript,图片) ...
- 项目使用文档管理:MediaWiki安装及使用入门
MediaWiki是著名的开源wiki引擎,全球最大的wiki项目维基百科(百科词条协作系统)是使用MediaWiki的成功范例,MediaWiki的最大作用在于对知识的归档,可用于构建企业/个人知识 ...
- SSM的Maven项目搭建过程
POM文件 父项目管理jar包,pom <modelVersion>4.0.0</modelVersion> <groupId>cn.e3mall</grou ...
- 设计模式--命令模式C++实现
命令模式C++实现 1定义 将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求队列或者记录请求日志,可以提供命令的撤销和恢复功能 2类图 角色描述: Receiver接受者角色,就 ...
- flask学习(十):模板中访问模型和字典的属性
访问模型中的属性或者是字典,可以通过{{params.property}}的形式,或者是使用{{params['age']}}这样的形式
- 25.大白话说java并发工具类-CountDownLatch,CyclicBarrier,Semaphore,Exchanger
1. 倒计时器CountDownLatch 在多线程协作完成业务功能时,有时候需要等待其他多个线程完成任务之后,主线程才能继续往下执行业务功能,在这种的业务场景下,通常可以使用Thread类的join ...
- ASP.NET网站部署CentOS操作笔记
ASP.NET 网站部署 Linux 服务器简要笔记 Mono 刚问世的时候,跑起来确实有很多不可预估的 BUG,但是被微软收购后推出的几个版本相对来说稳定了许多. 这几天使用了一个 n 年前用 We ...