2555: SubString[LCT+SAM]
2555: SubString
Time Limit: 30 Sec Memory Limit: 512 MB
Submit: 2601 Solved: 780
[Submit][Status][Discuss]
Description
懒得写背景了,给你一个字符串init,要求你支持两个操作
(1):在当前字符串的后面插入一个字符串
(2):询问字符串s在当前字符串中出现了几次?(作为连续子串)
你必须在线支持这些操作。
Input
第一行一个数Q表示操作个数
第二行一个字符串表示初始字符串init
接下来Q行,每行2个字符串Type,Str
Type是ADD的话表示在后面插入字符串。
Type是QUERY的话表示询问某字符串在当前字符串中出现了几次。
为了体现在线操作,你需要维护一个变量mask,初始值为0
读入串Str之后,使用这个过程将之解码成真正询问的串TrueStr。
询问的时候,对TrueStr询问后输出一行答案Result
然后mask = mask xor Result
插入的时候,将TrueStr插到当前字符串后面即可。
HINT:ADD和QUERY操作的字符串都需要解压
Output
Sample Input
2
A
QUERY B
ADD BBABBBBAAB
Sample Output
0
HINT
40 % 的数据字符串最终长度 <= 20000,询问次数<= 1000,询问总长度<= 10000
100 % 的数据字符串最终长度 <= 600000,询问次数<= 10000,询问总长度<= 3000000
新加数据一组--2015.05.20
Source
- 答案显然是目标串状态的right集合的大小,因为要在线我们可以用LCT来维护parent树。也就是说每次将当前点到根节点路径上的right +1。
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
//---------------------LCT----------------------
const int M=3e6+;
int n,m,fa[M],st[M],c[M][];
bool rev[M];
int tag[M];
int val[M];
bool isroot(int x){
return c[fa[x]][]!=x&&c[fa[x]][]!=x;
}
/*void update(int x){
val[x]=val[c[x][0]]+val[c[x][1]]+1;
}*/
void opera(int x,int v){
if(x) tag[x]+=v,val[x]+=v;
}
void rotate(int x){
int y=fa[x],z=fa[y],l,r;
l=(c[y][]==x);r=l^;
if(!isroot(y)) c[z][c[z][]==y]=x;
fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
c[y][l]=c[x][r];c[x][r]=y;
//update(y);update(x);
}
#define l c[x][0]
#define r c[x][1]
void pushdown(int x){
/*if(rev[x]){
rev[x]^=1;rev[l]^=1;rev[r]^=1;
swap(l,r);
}*/
if(tag[x]){
opera(l,tag[x]);
opera(r,tag[x]);
tag[x]=;
}
}
void splay(int x){
int top=;st[++top]=x;
for(int i=x;!isroot(i);i=fa[i]) st[++top]=fa[i];
for(int i=top;i;i--) pushdown(st[i]);
while(!isroot(x)){
int y=fa[x],z=fa[y];
if(!isroot(y)){
if((c[y][]==x)^(c[z][]==y)) rotate(x);
else rotate(y);
}
rotate(x);
}
}
void access(int x){
for(int t=;x;x=fa[x]) splay(x),c[x][]=t,t=x;
}
/*void evert(int x){
access(x);splay(x);rev[x]^=1;
}*/
void link(int x,int y){
fa[x]=y;access(y);splay(y);
//evert(x);fa[x]=y;splay(x);
opera(y,val[x]);
}
/*void cut(int x,int y){
evert(x);
access(y);splay(y);
opera(y,-val[y]);
c[y][0]=fa[c[y][0]]=0;//!!!
}*/
void cut(int x){
access(x);splay(x);opera(l,-val[x]);
c[x][]=fa[c[x][]]=;
}
int find(int x){
access(x);splay(x);
for(;l;x=l);
return x;
}
#undef l
#undef r
//---------------------SAM----------------------
const int N=1.2e6+;
int p,q,np,nq;
int last,cnt,len,mask;
int l[N],par[N],tr[N][];
int siz[N];char s[N];
inline void extend(int c){
p=last;np=last=++cnt;val[np]=;l[np]=l[p]+;
for(;p&&!tr[p][c];tr[p][c]=np,p=par[p]);
if(!p) par[np]=,link(np,);
else{
q=tr[p][c];
if(l[p]+==l[q]) par[np]=q,link(np,q);
else{
nq=++cnt;l[nq]=l[p]+;cut(q);
memcpy(tr[nq],tr[q],sizeof tr[q]);
par[nq]=par[q];
link(nq,par[q]);
// siz[nq]=siz[q];
par[np]=par[q]=nq;
link(np,nq);link(q,nq);
for(;tr[p][c]==q;tr[p][c]=nq,p=par[p]);
}
}
// for(;np;np=par[np]) siz[np]++;
}
inline void build(){
for(int i=;i<len;i++) extend(s[i]-'A');
}
inline int query(){
int p=;
for(int i=,c;i<len;i++){
c=s[i]-'A';
if(!tr[p][c]) return ;
p=tr[p][c];
}
splay(p);
mask^=val[p];
return val[p];
}
inline void decode(int mask){
len=strlen(s);
for(int i=;i<len;i++){
mask=(mask*+i)%len;
swap(s[mask],s[i]);
}
}
int main(){
last=++cnt;
scanf("%d",&m);scanf("%s",s);len=strlen(s);
build();
for(char op[];m--;){
scanf("%s%s",op,s);decode(mask);
if(op[]=='A')
build();
else
printf("%d\n",query());
}
return ;
}
2555: SubString[LCT+SAM]的更多相关文章
- 【BZOJ 2555】 2555: SubString (SAM+LCT)
2555: SubString Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 2548 Solved: 762 Description 懒得写背景了 ...
- bzoj 2555 SubString(SAM+LCT)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2555 [题意] 给定一个字符串,可以随时插入字符串,提供查询s在其中作为连续子串的出现 ...
- P5212 SubString LCT+SAM
$ \color{#0066ff}{ 题目描述 }$ 给定一个字符串init,要求支持两个操作 在当前字符串的后面插入一个字符串 询问字符串ss在当前字符串中出现了几次?(作为连续子串) 强制在线. ...
- bzoj 2555: SubString 后缀自动机+LCT
2555: SubString Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 688 Solved: 235[Submit][Status][Dis ...
- 字符串(LCT,后缀自动机):BZOJ 2555 SubString
2555: SubString Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 1620 Solved: 471 Description 懒得写背景了 ...
- BZOJ 2555 SubString(LCT+后缀树)
喜闻乐见的LCT+SAM 此题要求动态插入,直接上后缀树.然后询问其实就是求一个节点的子树后缀结束节点的个数. 因为建立后缀树需要插入和删除,就直接上LCT.每次加入一个点,把它到根的路径加一 (现在 ...
- 2555: SubString
2555: SubString 链接 题意: 动态在末尾加入一个字符串,询问一个字符串出现了多少次. 分析: 如果没有动态加入,那么建出SAM后,求出parent树上,每个点|Right|,然后走一遍 ...
- [BZOJ2555]SubString LCT+后缀自动机
2555: SubString Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 3253 Solved: 975[Submit][Status][Di ...
- 【刷题】BZOJ 2555 SubString
Description 懒得写背景了,给你一个字符串init,要求你支持两个操作 (1):在当前字符串的后面插入一个字符串 (2):询问字符串s在当前字符串中出现了几次?(作为连续子串) 你必须在线支 ...
随机推荐
- git解决冲突(rebase版)
当使用git rebase碰到冲突时, git rebase <Remote Branch>/<Your Branch> 信息如下: error: Failed to merg ...
- wine for MacOS
Installing Wine on Mac This tutorial is for intermediate users who want to install and use Wine on t ...
- VS2010 正则批量替换头文件路径
最近在项目实践中,需要统一对工程头文件进行重构,具体要求是,将之前 #include "../../abc/def.h" 类似的头文件引用路径 替换为#include &q ...
- 使用 Python 解数学方程
SymPy是符号数学的Python库.它的目标是成为一个全功能的计算机代数系统,同时保持代码简洁.易于理解和扩展 服务器Ubuntu 1.安装Python 2.安装SymPy库 sudo pip in ...
- 使用jquery操作session
摘要: 今天分享的是使用jquery来处理session.我们将使用sessionStorage对象,它类似与localStorage对象,只是sessionStorage是用来储存session数据 ...
- C#静态构造函数调用机制
https://blog.csdn.net/cjolj/article/details/56329230 若一个类中有静态构造函数,在首次实例化该类或任何的静态成员被引用时,.NET自动调用静态构造函 ...
- Linux+Redis实战教程_day03_4、通用redis命令【重点】
4.通用redis命令[重点] Redis五种数据类型,String,hash,list,set,有序set l keys pattern:获取所有与pattern匹配的key,返回所有与该key匹配 ...
- Git Step by Step – (6) Git远程仓库
前面文章中出现的所有Git操作都是基于本地仓库的,但是日常工作中需要多人合作,不可能一直都在自己的代码仓库工作.所以,这里我们就开始介绍Git远程仓库. 在Git系统中,用户可以通过push/pull ...
- 统计js数组中奇数元素的个数
如何统计一个JS数组中奇数元素的个数呢? 这是群友提出的一个问题,大部分群友给出的是遍历 然后对2取模,得到最终结果. 这样的写法是最容易想得到的,那么有没有其他思路呢? 这里我提供另外一种思路,我们 ...
- 存储过程中SELECT INTO的使用
在MySQL存储过程中使用SELECT …INTO语句为变量赋值: 用来将查询返回的一行的各个列值保存到局部变量中. 要求: 查询的结果集中只能有1行. SELECT col_name[,...] I ...