字符串(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] ...
随机推荐
- HDU 4296 Buildings(贪心)
题意: 给定n个建筑物,每个建筑物都有两个属性w, s,每个建筑物都有一个PDV = (Σw j)-s i .意思就是它上面的所有的w相加减去它的s,让求怎么放置这个建筑物使得每个建筑物当中PDV最大 ...
- iBatis 的修改一个实体
Student.xml <update id="updateStudent" parameterClass="Student" > UPDATE S ...
- JQ 让光标在文本框最末尾
function setFocus() { //文本末尾获得焦点 var obj = event.srcElement; var txt = obj.createTextRange(); txt.mo ...
- PAT_2-08. 用扑克牌计算24点
一副扑克牌的每张牌表示一个数(J.Q.K分别表示11.12.13,两个司令都表示6).任取4张牌,即得到4个1~13的数,请添加运算符 (规定为加+ 减- 乘* 除/ 四种)使之成为一个运算式.每个数 ...
- 【POJ1823】【线段树】Hotel
Description The "Informatics" hotel is one of the most luxurious hotels from Galaciuc. A l ...
- 计算机天才Aaron Swartz 名作 《如何提高效率》——纪念真正的“hacker"!
如何提高效率 <HOWTO: Be more productive>(如何提高效率)作者:Aaron Swartz 肯定有人跟你说过这样的话,“你有看电视的那么长时间,都可以用来写一本书了 ...
- 【转】 C语言自增自减运算符深入剖析
转自:http://bbs.csdn.net/topics/330189207 C语言的自增++,自减--运算符对于初学者来说一直都是个难题,甚至很多老手也会产生困惑,最近我在网上看到一个问题:#in ...
- 《zip命令》-linux命令五分钟系列之九
本原创文章属于<Linux大棚>博客. 博客地址为http://roclinux.cn. 文章作者为roc 希望您能通过捐款的方式支持Linux大棚博客的运行和发展.请见“关于捐款” == ...
- 实用的透明背景mark图标
- html5 DeviceOrientation来实现手机网站上的摇一摇功能
原文地址:http://www.cootm.com/?p=706 从网上转载看到的,感觉不错,就转过来了,特此感谢 cnblogs 的 幸福2胖纸的码农生活,直接转载了,不要介意!呵呵 以下是转载内容 ...