2555: SubString

Time Limit: 30 Sec  Memory Limit: 512 MB
Submit: 1620  Solved: 471

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

  注意这个mask不会在函数内改变……

 #include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn=;
int cnt,last;
int FA[maxn],CH[maxn][],len[maxn],rt[maxn];
int fa[maxn],ch[maxn][],add[maxn],key[maxn],flip[maxn]; void Add(int x,int d){
if(!x)return;
key[x]+=d;
add[x]+=d;
} void Flip(int x){
swap(ch[x][],ch[x][]);
flip[x]^=;
} void Push_down(int x){
if(add[x]){
Add(ch[x][],add[x]);
Add(ch[x][],add[x]);
add[x]=;
}
if(flip[x]){
Flip(ch[x][]);
Flip(ch[x][]);
flip[x]=;
}
} void Rotate(int x){
int y=fa[x],g=fa[y],c=ch[y][]==x;
ch[y][c]=ch[x][c^];fa[ch[y][c]]=y;
ch[x][c^]=y;fa[y]=x;fa[x]=g;
if(rt[y])rt[y]=false,rt[x]=true;
else ch[g][ch[g][]==y]=x;
} void P(int x){
if(!rt[x])P(fa[x]);
Push_down(x);
} void Splay(int x){
P(x);
for(int y=fa[x];!rt[x];Rotate(x),y=fa[x])
if(!rt[y])Rotate((ch[fa[y]][]==y)==(ch[y][]==x)?y:x);
} void Access(int x){
int y=;
while(x){
Splay(x);
rt[ch[x][]]=true;
rt[ch[x][]=y]=false;
x=fa[y=x];
}
} void Lca(int &x,int &y){
Access(y);y=;
while(true){
Splay(x);
if(!fa[x])break;
rt[ch[x][]]=true;
rt[ch[x][]=y]=false;
x=fa[y=x];
}
} void Make_rt(int x){
Access(x);
Splay(x);
Flip(x);
} void Change(int x,int y,int d){
Lca(x,y);key[x]+=d;
Add(y,d);Add(ch[x][],d);
} void Link(int x,int y){
Make_rt(x);
Splay(x);
fa[x]=y;
Change(,y,key[x]);
} void Cut(int x,int y){
Make_rt(x);
Splay(y);
fa[ch[y][]]=fa[y];
fa[y]=;rt[ch[y][]]=true;
ch[y][]=;
Change(,y,-key[x]);
} struct SAM{
void Init(){
memset(FA,,sizeof(FA));
memset(CH,,sizeof(CH));
memset(rt,-,sizeof(rt));
last=cnt=;
} void Insert(int c){
int p=last,np=last=++cnt;len[np]=len[p]+;key[np]=;
while(p&&!CH[p][c])CH[p][c]=np,p=FA[p];
if(!p)FA[np]=;
else{
int q=CH[p][c];
if(len[p]+==len[q])
FA[np]=q;
else{
int nq=++cnt;len[nq]=len[p]+;
memcpy(CH[nq],CH[q],sizeof(CH[q]));
FA[nq]=FA[q];FA[q]=FA[np]=nq; Link(nq,FA[nq]);Cut(q,FA[nq]);Link(q,nq); while(CH[p][c]==q)
CH[p][c]=nq,p=FA[p];
}
}
Link(np,FA[np]);
}
void Extend(char *s){
int l=strlen(s);
for(int i=;i<l;i++)
Insert(s[i]-'A');
} int Solve(char *s){
int l=strlen(s),p=;
for(int i=,c;i<l;i++){
c=s[i]-'A';
if(!CH[p][c])return ;
else p=CH[p][c];
}
Splay(p);
return key[p];
}
}sam; char s[maxn];
char op[];
int ans,mask,Q; void Decode(char *str,int t){
int l=strlen(str);
for(int i=;i<l;i++){
t=(t*+i)%l;
swap(str[i],str[t]);
}
} int main(){
sam.Init();
scanf("%d",&Q);
scanf("%s",s);
sam.Extend(s);
while(Q--){
scanf("%s",op);
scanf("%s",s);Decode(s,mask);
if(op[]=='A')
sam.Extend(s);
else{
ans=sam.Solve(s);
printf("%d\n",ans);
mask^=ans;
}
}
return ;
}

字符串(LCT,后缀自动机):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. bzoj 2555 SubString —— 后缀自动机+LCT

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

  3. bzoj 2555: SubString【后缀自动机+LCT】

    一直WA--找了半天错的发现居然是解密那里的mask其实是不能动的--传进去的会变,但是真实的那个不会变-- 然后就是后缀自动机,用LCT维护parent树了--注意不能makeroot,因为自动机的 ...

  4. bzoj 2555 SubString(SAM+LCT)

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

  5. [BZOJ2555]SubString LCT+后缀自动机

    2555: SubString Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 3253  Solved: 975[Submit][Status][Di ...

  6. BZOJ 3473: 字符串 [广义后缀自动机]

    3473: 字符串 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 354  Solved: 160[Submit][Status][Discuss] ...

  7. bzoj 3277: 串 & bzoj 3473: 字符串【后缀自动机||后缀数组】

    建一个广义后缀自动机(每加完一个串都返回root),在parent树上dpsum记录合法长度,打着时间戳往上跳,最后每个串在自动机上跑一变统计答案即可. 后缀数组理解起来可能方便一点,但是难写,就只说 ...

  8. ●BZOJ 2555 SubString

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

  9. 【BZOJ-1396&2865】识别子串&字符串识别 后缀自动机/后缀树组 + 线段树

    1396: 识别子串 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 312  Solved: 193[Submit][Status][Discuss] ...

随机推荐

  1. C# 自定义控件制作和使用实例(winform)

    C# 自定义用户控件 此处为转载文章,用于记录自我学习过程,原文链接地址http://blog.csdn.net/xiongxuanwen/article/details/2605109 上篇:控件制 ...

  2. 安卓工程修改包名后 Failed to find provider info for...问题

    安卓工程修改包名后 Failed to find provider info for com.android...provider问题 原因: 1. 多处含包名文件须同时更改 2. Manifest里 ...

  3. ResultSetMetaData rsmd = rs.getMetaData()是什么意思?

    ResultSetMetaData rsmt=rs.getMetaData(); 得到结果集(rs)的结构,比如字段数.字段名等.使用rs.getMetaData().getTableName(1)) ...

  4. [转]mysql导入导出数据中文乱码解决方法小结

    本文章总结了mysql导入导出数据中文乱码解决方法,出现中文乱码一般情况是导入导入时编码的设置问题,我们只要把编码调整一致即可解决此方法,下面是搜索到的一些方法总结,方便需要的朋友. linux系统中 ...

  5. VS 编程常见错误及解决方法

    1. VS2013 无法打开包括文件:“cv.h"等一些头文件 解决方法: cv.h是build\include文件夹下的头文件,所在文件夹位置是D:\Program Files (x86) ...

  6. 在用VC编译下debug和release的什么区别

    DEBUG和RELEASE 版本差异及调试相关问题:.         内存分配问题 1.          变量未初始化.下面的程序在debug中运行的很好. thing * search(thin ...

  7. 【HOJ1356】【Miller_rabin素性测试】Prime Judge

    Given a positive integer, your job is writing a program to determine whether it is a prime number or ...

  8. 封装Timer

    System.Timers.Timer,System.Timers.Timer在使用的过程中需要: 1.构造函数不同,构造函数可以什么事情也不做,也可以传入响应间隔时间:System.Timers.T ...

  9. java 下载文件 内容为空。

    检查下是不是io流没有关闭,记得关闭所有流.

  10. BAE Flask UEditor 使用七牛云

    1. 配置BAE支持七牛云的SDK BAE的python requirements当然不支持竞争对手了. 解决方法: 把qiniu这个文件包直接放置在你项目的目录中(与其他app同级) 运行会发现缺少 ...