2555: SubString

Time Limit: 30 Sec  Memory Limit: 512 MB
Submit: 3253  Solved: 975
[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

Ctsc模拟赛By 洁妹

显然我们要求当前子串子树的后缀结束结点个数。

要在线实现,用lct维护sam

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define maxn 1200000
using namespace std;
int mask;
char st[];
string chars;
void gets(int mask) {
scanf("%s",st);
chars=st;
for(int j=;j<chars.length();j++) {
mask=(mask*+j)%chars.length();
char t=chars[j];
chars[j]=chars[mask];
chars[mask]=t;
}
}
struct data {
int last,cnt;
int son[maxn][],link[maxn],step[maxn];
data() {last=cnt=;}
struct lct {
int fa[maxn],s[maxn][],v[maxn],tag[maxn];
bool isroot(int x) {return s[fa[x]][]!=x&&s[fa[x]][]!=x;}
void add(int x,int y){if(x) v[x]+=y,tag[x]+=y;}
void pushdown(int x) {
if(tag[x]) {
add(s[x][],tag[x]);add(s[x][],tag[x]);
tag[x]=;
}
}
void push(int x) {
if(!isroot(x)) push(fa[x]);
pushdown(x);
}
void rorate(int x) {
int y=fa[x],z=fa[y];
bool l=(s[y][]==x),r=l^;
if(!isroot(y)) s[z][s[z][]==y]=x;
fa[x]=z;fa[y]=x;s[y][l]=s[x][r];
fa[s[x][r]]=y;s[x][r]=y;
}
void splay(int x) {
push(x);
while(!isroot(x)) {
int y=fa[x],z=fa[y];
if(!isroot(y)) {
if(s[y][]==x^s[z][]==y) rorate(x);
else rorate(y);
}
rorate(x);
}
}
void access(int x) {for(int t=;x;t=x,x=fa[x]) {splay(x);s[x][]=t;}}
void link(int x,int y) {fa[x]=y;access(y);splay(y);add(y,v[x]);}
void cut(int x) {access(x);splay(x);add(s[x][],-v[x]);s[x][]=fa[s[x][]]=;}
}t;
void extend(int c) {
int p=last,np=last=++cnt;step[np]=step[p]+;t.v[np]=;
while(p&&!son[p][c]) son[p][c]=np,p=link[p];
if(!p) link[np]=,t.link(np,);
else {
int q=son[p][c];
if(step[q]==step[p]+) link[np]=q,t.link(np,q);
else {
int nq=++cnt;
memcpy(son[nq],son[q],sizeof(son[q]));
link[nq]=link[q];t.link(nq,link[q]);
link[q]=link[np]=nq;
t.cut(q);t.link(np,nq);t.link(q,nq);
step[nq]=step[p]+;
while(son[p][c]==q&&p) son[p][c]=nq,p=link[p];
}
}
}
void add() {
gets(mask);
int l=chars.length();
for(int i=;i<l;i++) extend(chars[i]-'A');
}
int query() {
gets(mask);
int p=,l=chars.length();
for(int i=;i<l;i++) {
p=son[p][chars[i]-'A'];if(!p) return ;
}
t.splay(p);
return t.v[p];
}
}sam;
int main() {
int Q;scanf("%d",&Q);
scanf("%s",st+);
int len=strlen(st+);
for(int i=;i<=len;i++) sam.extend(st[i]-'A');
while(Q--) {
char s[];
scanf("%s",s);
if(s[]=='A') sam.add();
else {
int ans=sam.query();
printf("%d\n",ans);
mask^=ans;
}
}
}

[BZOJ2555]SubString LCT+后缀自动机的更多相关文章

  1. bzoj2555 substring(LCT 后缀自动机)

    /* 动态求right集合的大小 LCT维护parent树即可 注意 由于树是有向的不会换根并且每次操作单一, 于是不需要维护子树和(写起来很麻烦) 直接打标记修改即可 */ #include< ...

  2. BZOJ2555 SubString 【后缀自动机 + LCT】

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

  3. BZOJ2555: SubString(后缀自动机,LCT维护Parent树)

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

  4. BZOJ2555 SubString【后缀自动机+LCT】

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

  5. BZOJ2555 SubString(后缀自动机+LCT)

    询问串放在SAM上不跳fail跑到的节点的|right|即为答案.用LCT维护parent树即可.可以直接维护子树信息,也可以转化为路径加.注意强制在线所使用的mask是作为参数传进去的. #incl ...

  6. 【BZOJ2555】SubString(后缀自动机,Link-Cut Tree)

    [BZOJ2555]SubString(后缀自动机,Link-Cut Tree) 题面 BZOJ 题解 这题看起来不难 每次要求的就是\(right/endpos\)集合的大小 所以搞一个\(LCT\ ...

  7. spoj 7258 Lexicographical Substring Search (后缀自动机)

    spoj 7258 Lexicographical Substring Search (后缀自动机) 题意:给出一个字符串,长度为90000.询问q次,每次回答一个k,求字典序第k小的子串. 解题思路 ...

  8. 【SPOJ】Longest Common Substring(后缀自动机)

    [SPOJ]Longest Common Substring(后缀自动机) 题面 Vjudge 题意:求两个串的最长公共子串 题解 \(SA\)的做法很简单 不再赘述 对于一个串构建\(SAM\) 另 ...

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

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

随机推荐

  1. 创建一个doc对象时候 如果读取了一个已存在的xml对象时候 该xml对象的结构已存在doc中 当改变该doc结构时候 不需要创建新的doc对象

    创建一个doc对象时候 如果读取了一个已存在的xml对象时候 该xml对象的结构已存在doc中 当改变该doc结构时候不 需要创建新的doc对象 直接添加即可 他会同步过去

  2. POJ 3801/HDU 3157 Crazy Circuits | 有下界的最小流

    题目: POJ最近总是炸 所以还是用HDU吧http://acm.hdu.edu.cn/showproblem.php?pid=3157 题解: 题很长,但其实就是给个有源汇带下界网络流(+是源,-是 ...

  3. BZOJ 2005 2005: [Noi2010]能量采集 | 容斥原理

    题目: http://www.lydsy.com/JudgeOnline/problem.php?id=2005 题解: http://blog.csdn.net/popoqqq/article/de ...

  4. BZOJ3243 [Noi2013]向量内积 【乱搞】

    题目链接 BZOJ3243 题解 模数只有\(2\)或\(3\),可以大力讨论 如果模数为\(2\),乘积结果只有\(1\)或\(0\) 如果一个向量和前面所有向量乘积都为\(1\),那么其和前面向量 ...

  5. hadoop基础----hadoop实战(九)-----hadoop管理工具---CDH的错误排查(持续更新)

    在CDH安装完成后或者CDH使用过程中经常会有错误或者警报,需要我们去解决,积累如下: 解决红色警报 时钟偏差 这是因为我们的NTP服务不起作用导致的,几台机子之间有几秒钟的时间偏差. 这种情况下一是 ...

  6. taotao用户登录(及登录成功后的回调url处理)

    后台Controller: package com.taotao.sso.controller; import org.springframework.stereotype.Controller; i ...

  7. TCP ------ TCP四次挥手(断开连接)及断开过程

    1.正常情况下,调用close(),产生的其中一个效果就是发送FIN,只有双方都调用close(),才会出现正常的四次挥手. 2.如果是服务器,发起四次挥手是在关闭accept()返回的套接字,而不是 ...

  8. 关闭listener监听日志

    有几次碰到过由于监听日志文件大小达到几G,使得在连接时非常慢,像hang住一样,windows下的监听日志达到4G限制,后续连接如果无法写监听日志,就会产生TNS-12537报错,可以通过关闭写监听日 ...

  9. 理解SetCapture、ReleaseCapture、GetCapture(控制了消息发往哪个窗口,是理解消息的关键)

    理解SetCapture.ReleaseCapture.GetCapture 正常情况下,鼠标指针位于哪个窗口区域内,鼠标消息就自动发给哪个窗口.如果调用了SetCapture,之后无论鼠标的位置在哪 ...

  10. (转)Python中实现带Cookie的Http的Post请求

    转自crifan: http://www.crifan.com/python_http_post_request_with_cookie/ . . . .