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在当前字符串中出现了几次?(作为连续子串) 你必须在线支 ...
随机推荐
- ubuntu安装mongo数据库
安装mongo数据库,在shell下输入 sudo apt-get install mongodb 如果需要在Python中使用mongo数据库,还需要额外安装Python封装库 pip instal ...
- iOS:当点击 FormSheet 之外时,关闭该视图
@interface XXViewController (){ @property (strong, nonatomic) UITapGestureRecognizer *tapGesture; - ...
- iOS: 定义 Block
定义 typedef void (^RFAudioBasicBlock) (void); typedef void (^RFAudioSuccessBlock) (BOOL flag); typede ...
- windows使用技巧和工具(后面可能更新linux)
*:希望广大网友有什么建议或者好的用法工具.也能够在以下评论. 希望这是一个能够让我们更好工作起来的帖子. 工作也能舒适和开心呢. 想着好久没写过博客了吧.今天就写一篇关于windows的使用的吧.我 ...
- scala实现相邻两个元素挑换位置的代码,哈哈
import scala.math._ import breeze.plot._ import breeze.linalg._ import scala.collection.mutable.Arra ...
- EasyUI的功能树之扁平化
上篇博客主要介绍了异步加载树的方法,通过前台传给后台一个节点的id值,然后当单击节点加号时,查询并显示其子节点的数据.其实如果不是很大的数据,我们本可以次把树中所有节点都加载上来的.也就是说,我的Ac ...
- Android 布局学习之——LinearLayout属性baselineAligned的作用及baseline
相信大家对LinearLayout已经相当熟悉,但你们是否了解它的属性baselineAligned呢? Android官方文档是这么描述的:
- 75道阿里Java面试题,你能答上几道?
整理了下阿里近几年的java面试题目,大家参考下吧,希望对大家有帮助,可以帮大家查漏补缺. 答对以下这些面试题,可以淘汰掉 80 % 的求职竞争者. 1.hashcode相等两个类一定相等吗?equa ...
- andoid-sdk 安装时出现 Stopping ADB server failed(code -1) 错
出错原因: cmd在path路径找不到adb命令,是因为adb.exe文件存在于android-sdk安装目录platform-tools/子目录下,要将这个路径配置到环境变量里面. 解决方案: 按照 ...
- winform下通过webclient使用非流方式上传(post)数据和文件
这两天因为工作的需要,需要做一个winform上传数据到服务器端的程序.当时第一个想法是通过webservice的方式来实现,后来觉得麻 烦,想偷懒就没有用这样的方式,http的post方式变成了第一 ...