字符串(LCT,后缀自动机):BZOJ 2555 SubString
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
A
QUERY B
ADD BBABBBBAAB
Sample Output
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的更多相关文章
- 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 集合的大小,需要查询 ...
- bzoj 2555: SubString【后缀自动机+LCT】
一直WA--找了半天错的发现居然是解密那里的mask其实是不能动的--传进去的会变,但是真实的那个不会变-- 然后就是后缀自动机,用LCT维护parent树了--注意不能makeroot,因为自动机的 ...
- bzoj 2555 SubString(SAM+LCT)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2555 [题意] 给定一个字符串,可以随时插入字符串,提供查询s在其中作为连续子串的出现 ...
- [BZOJ2555]SubString LCT+后缀自动机
2555: SubString Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 3253 Solved: 975[Submit][Status][Di ...
- BZOJ 3473: 字符串 [广义后缀自动机]
3473: 字符串 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 354 Solved: 160[Submit][Status][Discuss] ...
- bzoj 3277: 串 & bzoj 3473: 字符串【后缀自动机||后缀数组】
建一个广义后缀自动机(每加完一个串都返回root),在parent树上dpsum记录合法长度,打着时间戳往上跳,最后每个串在自动机上跑一变统计答案即可. 后缀数组理解起来可能方便一点,但是难写,就只说 ...
- ●BZOJ 2555 SubString
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=2555题解: 后缀自动机+LCT 不难发现,对于输入的询问串,在自动机里trans后的到的状态 ...
- 【BZOJ-1396&2865】识别子串&字符串识别 后缀自动机/后缀树组 + 线段树
1396: 识别子串 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 312 Solved: 193[Submit][Status][Discuss] ...
随机推荐
- 转载:修改xshell中文乱码的问题(管用)
执行echo $LANG命令输出的是当前的编码方式,执行locale命令得到系统中所有可用的编码方式.要让Xshell不显示乱码,则要将编码方式改为UTF-8. 在Xshell中[file]-> ...
- (九)打印机驱动设置—USB接口的设置
佳博打印机代理商淘宝店https://shop107172033.taobao.com/index.htm?spm=2013.1.w5002-9520741823.2.Sqz8Pf 在此店购买的打印机 ...
- Solaris用户管理(一):用户与组管理
Solaris用户管理(一):用户与组管理 2008-07-01 09:19 用户管理是系统管理的基础.Solaris中不但支持传统Unix所支持的用户和组的概念,还从Solaris 8开始引入了基 ...
- linux 脚本编写基础(一)
1. Linux 脚本编写基础 1.1 语法基本介绍 1.1.1 开头 程序必须以下面的行开始(必须方在文件的第一行): #!/bin/sh 符号#!用来告诉系统它后面的参数是用来执行该文件的程序.在 ...
- iOS_ruby环境的配置
AC机中安装RUBY环境 转自:http://www.cnblogs.com/foxting/p/4520829.html 在安装CocoaPods之前要先配置好RUBY环境,本文就怎么安装RUBY ...
- iOS6以后的单个控制器横竖屏显示以及旋转屏控制技巧,附带iOS8以后显示电池状态栏
一.在应用中从竖屏模式强制转换为横屏模式 第一种方法:通过模态弹出视图的方式,使得特定ViewController坚持特定的interfaceOrientation(1)iOS6之后提供了这样一个方法 ...
- %s的用法
%s 正常输出字符串printf("%s\n", "abcd"); //normal output abcd %8s 最少输出8位长度的字符串,不够在字符串左侧 ...
- JSP语法
第3章 JSP语法 [本章专家知识导学] JSP是建立在Java语言基础上的一种Web程序设计语言,具有自己特有的用法和指令.本章首先介绍JSP页面的程序结构,然后讲述JSP程序中经常用到基本的面向 ...
- (转载)50个c/c++源代码网站
C/C++是最主要的编程语言.这里列出了50名优秀网站和网页清单,这些网站提供c/c++源代码.这份清单提供了源代码的链接以及它们的小说明.我已 尽力包括最佳的C/C++源代码的网站.这不是一个完整的 ...
- C++类型转换运算符
C++中提供4中类型转运算符,分别是:static_cast.dynamic_cast.reinterpret_cast和const_cast; 语法格式如下: 类型转换运算符 < type_i ...