博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[BZOJ2555]SubString(SAM+LCT)
阅读量:5142 次
发布时间:2019-06-13

本文共 2640 字,大约阅读时间需要 8 分钟。

2555: SubString

Time Limit: 30 Sec  Memory Limit: 512 MB
Submit: 4077  Solved: 1236
[][][]

Description

懒得写背景了,给你一个字符串init,要求你支持两个操作
(1):在当前字符串的后面插入一个字符串
(2):询问字符串s在当前字符串中出现了几次?(作为连续子串)
你必须在线支持这些操作。

Input

第一行一个数Q表示操作个数
第二行一个字符串表示初始字符串init
接下来Q行,每行2个字符串Type,Str
Type是ADD的话表示在后面插入字符串。
Type是QUERY的话表示询问某字符串在当前字符串中出现了几次。
为了体现在线操作,你需要维护一个变量mask,初始值为0 

    

读入串Str之后,使用这个过程将之解码成真正询问的串TrueStr。
询问的时候,对TrueStr询问后输出一行答案Result
然后mask=maskxorResult
插入的时候,将TrueStr插到当前字符串后面即可。
HINT:ADD和QUERY操作的字符串都需要解压
长度 <= 600000,询问次数<= 10000,询问总长度<= 3000000
新加数据一组--2015.05.20

Output

Sample Input

2
A
QUERY B
ADD BBABBBBAAB

Sample Output

0

HINT

Source

[ ][ ][ ]

后缀自动机,每次查询的是一个点的Right。

发现每次改变fa[]实际上是在pre树上的一次Cut和Link操作,所以用LCT维护就好了。

1 #include
2 #include
3 #include
4 #define ls ch[x][0] 5 #define rs ch[x][1] 6 #define rep(i,l,r) for (int i=l; i<=r; i++) 7 using namespace std; 8 9 const int N=1200010;10 int Q,len,lst=1,cnt=1,mask,f[N],sm[N],ch[N][2],tag[N],w[N],son[N][27],mx[N],fa[N];11 char op[10],S[3000100];12 13 bool isroot(int x){ return (!f[x]) || (ch[f[x]][0]!=x && ch[f[x]][1]!=x); }14 void put(int x,int k){ w[x]+=k; tag[x]+=k; }15 void push(int x){ if (tag[x]) put(ls,tag[x]),put(rs,tag[x]),tag[x]=0; }16 void pd(int x){ if (!isroot(x)) pd(f[x]); push(x); }17 18 void rot(int x){19 int y=f[x],z=f[y],w=ch[y][1]==x;20 if (!isroot(y)) ch[z][ch[z][1]==y]=x;21 f[x]=z; f[y]=x; f[ch[x][w^1]]=y;22 ch[y][w]=ch[x][w^1]; ch[x][w^1]=y;23 }24 25 void splay(int x){26 pd(x);27 while (!isroot(x)){28 int y=f[x],z=f[y];29 if (!isroot(y)) rot((ch[z][0]==y)^(ch[y][0]==x) ? x : y);30 rot(x);31 }32 }33 34 void access(int x){ for (int y=0; x; y=x,x=f[x]) splay(x),ch[x][1]=y; }35 void link(int x,int y){ f[x]=y; access(y); splay(y); put(y,w[x]); }36 void cut(int x){ access(x); splay(x); put(ls,-w[x]); f[ls]=0; ch[x][0]=0; }37 int que(int x){ splay(x); return w[x]; }38 39 void ext(int c){40 int p=lst,np=lst=++cnt; mx[np]=mx[p]+1; w[np]=1;41 while (p && !son[p][c]) son[p][c]=np,p=fa[p];42 if (!p) fa[np]=1,link(np,1);43 else{44 int q=son[p][c];45 if (mx[q]==mx[p]+1) fa[np]=q,link(np,q);46 else{47 int nq=++cnt; mx[nq]=mx[p]+1;48 while (p && son[p][c]==q) son[p][c]=nq,p=fa[p];49 memcpy(son[nq],son[q],sizeof(son[q]));50 fa[nq]=fa[q]; link(nq,fa[q]);51 cut(q); fa[np]=fa[q]=nq; link(np,nq); link(q,nq);52 }53 }54 }55 56 void get(int mask){57 scanf("%s",S); len=strlen(S);58 for (int i=0; i

 

转载于:https://www.cnblogs.com/HocRiser/p/8986579.html

你可能感兴趣的文章
Tour HDU - 3488
查看>>
java反射详解zz
查看>>
mysql 导出表结构和表数据 mysqldump用法
查看>>
Ubuntu下忘记MySQL密码重设方法
查看>>
+new Date()的用法
查看>>
[LeetCode#128]Longest Consecutive Sequence
查看>>
[HAOI2008] 移动玩具
查看>>
vue使用vue-resource,进行网络请求
查看>>
Git 使用
查看>>
logstash编写2以及结合kibana使用
查看>>
UIResponder
查看>>
Android N 通知概览及example
查看>>
50 个 jQuery 插件可将你的网站带到另外一个高度
查看>>
玩转OneNET物联网平台之MQTT服务① —— OneNetMqtt全方位调试
查看>>
日本語勉強の日記 十二回目
查看>>
JavaScript 语句 while
查看>>
Function eregi() is deprecated (解决方法)
查看>>
155-PHP stripos函数
查看>>
105-PHP使用var_dump查看类的类型
查看>>
C++内存管理阅读笔记
查看>>