题目描述

(1):在当前字符串的后面插入一个字符串
(2):询问字符串s在当前字符串中出现了几次?(作为连续子串)
你必须在线支持这些操作。
题解
做法很自然,建出后缀自动机,维护每个节点的right集合,对于询问直接在sam上跑就好了。
然后它是在线的,得用LCT维护。
然后细节极多,首先必须维护好树的形态,也就是说不能makeroot,所以我的link就长这样。
inline void link(int x,int y){
access(x);splay(x);access(y);splay(y);
f[x]=y;si[y]+=size[x];pushup(y);
}

然后cut长这样

inline void cut(int x,int y){
access(x);splay(x);
f[tr[x][]]=;tr[x][]=;
pushup(x);
}

所以在这颗LCT中,每个点的左儿子维护的是它的父亲,然后我们在算子树和的时候把左儿子扣掉就好了。

断断续续淦了三天,极菜。

#include<iostream>
#include<cstdio>
#include<cstring>
#define N 1300002
using namespace std;
int size[N],ch[N][],tr[N][],fa[N],si[N],last,cnt,n,l[N],q,f[N],val[N];
int mark;
char s[N],qs[];
inline void pushup(int x){size[x]=size[tr[x][]]+size[tr[x][]]+si[x]+val[x];}
inline bool ge(int x){return tr[f[x]][]==x;}
inline bool isroot(int x){return tr[f[x]][]!=x&&tr[f[x]][]!=x;}
inline void rotate(int x){
int y=f[x],o=ge(x);
if(isroot(x))return;
tr[y][o]=tr[x][o^];f[tr[y][o]]=y;
if(!isroot(y))tr[f[y]][ge(y)]=x;f[x]=f[y];
f[y]=x;tr[x][o^]=y;pushup(y);pushup(x);
}
inline void splay(int x){
while(!isroot(x)){
int y=f[x];
if(isroot(y))rotate(x);
else rotate(ge(x)==ge(y)?y:x),rotate(x);
}
}
inline void access(int x){
for(int y=;x;y=x,x=f[x]){
splay(x);
si[x]+=size[tr[x][]];si[x]-=size[y];tr[x][]=y;
pushup(x);
}
}
inline void link(int x,int y){
access(x);splay(x);access(y);splay(y);
f[x]=y;si[y]+=size[x];pushup(y);
}
inline void cut(int x,int y){
access(x);splay(x);
f[tr[x][]]=;tr[x][]=;
pushup(x);
}
void Decode(char *ch,int mask){
int l=strlen(ch+);
for(int i=;i<l;++i){
mask=(mask*+i)%l;
swap(ch[i+],ch[mask+]);
}
}
inline void ins(int x){
int p=last,np=++cnt;last=np;l[np]=l[p]+;size[np]=val[np]=;
for(;p&&!ch[p][x];p=fa[p])ch[p][x]=np;
if(!p)fa[np]=,link(np,);
else{
int q=ch[p][x];
if(l[p]+==l[q])fa[np]=q,link(np,q);
else{
int nq=++cnt;l[nq]=l[p]+;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
int y=fa[q];cut(q,y);link(nq,y);
fa[nq]=fa[q];fa[q]=fa[np]=nq;
link(q,nq);link(np,nq);
for(;ch[p][x]==q;p=fa[p])ch[p][x]=nq;
}
}
}
int query(int n){
int now=;
for(int i=;i<=n;++i)if(ch[now][s[i]-'A'])now=ch[now][s[i]-'A'];else return ;
access(now);splay(now);
return size[now]-size[tr[now][]];
}
int main(){
scanf("%d",&q);
scanf("%s",s+);n=strlen(s+);last=cnt=;
for(int i=;i<=n;++i)ins(s[i]-'A');
while(q--){
scanf("%s",qs);scanf("%s",s+);n=strlen(s+);
Decode(s,mark);
if(qs[]=='Q'){
int x=query(n);mark^=x;printf("%d\n",x);
}
else for(int i=;i<=n;++i)ins(s[i]-'A');
}
return ;
}

bzoj2555(后缀自动机+LCT)的更多相关文章

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

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

  2. 51nod 1600 Simple KMP【后缀自动机+LCT】【思维好题】*

    Description 对于一个字符串|S|,我们定义fail[i],表示最大的x使得S[1..x]=S[i-x+1..i],满足(x<i) 显然对于一个字符串,如果我们将每个0<=i&l ...

  3. bzoj 2555 SubString —— 后缀自动机+LCT

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

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

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

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

    [BZOJ2555]SubString Description 懒得写背景了,给你一个字符串init,要求你支持两个操作         (1):在当前字符串的后面插入一个字符串         (2 ...

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

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

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

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

  8. 【BZOJ4545】DQS的trie 后缀自动机+LCT

    [BZOJ4545]DQS的trie Description DQS的自家阳台上种着一棵颗粒饱满.颜色纯正的trie. DQS的trie非常的奇特,它初始有n0个节点,n0-1条边,每条边上有一个字符 ...

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

    2555: SubString Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 688  Solved: 235[Submit][Status][Dis ...

随机推荐

  1. 17-vue-cli脚手架安装和webpack-simple模板项目生成

    ue-cli 是一个官方发布 vue.js 项目脚手架,使用 vue-cli 可以快速创建 vue 项目. GitHub地址是:https://github.com/vuejs/vue-cli 一.安 ...

  2. 关于JS动画和CSS3动画的性能差异

    本文章为综合其它资料所得. 根据Google Developer,Chromium项目里,渲染线程分为main thread和compositor thread. 如果CSS动画只是改变transfo ...

  3. springboot注解@SpringBootApplication分析

    @SpringBootApplication注解用在Spring Boot的入口类上面,是Spring Boot提供的应用启动相关的注解. 直接上注解的源码: @Target(ElementType. ...

  4. POJ_1185_炮兵阵地 dp+状态压缩

    题目:炮兵阵地 链接:http://poj.org/problem?id=1185 解题思路: 首先用 int 来表示每一行的情况,比如说第一行是k1,那么[ k1&(k1>>2) ...

  5. zTree树形菜单交互选项卡效果实现

    1. 添加自定义属性 page 2. 为 ztree 每个树形节点,添加点击事件 <!DOCTYPE html> <html> <head> <meta ch ...

  6. Day3-1 函数

    定义: 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可 特性: 减少重复代码 使程序变的可扩展 使程序变得易维护 语法: def calc(x, y): ...

  7. MySQL Connector/ODBC 2.50 (MyODBC 2.50)连接方式

    一.MySQL Connector/ODBC 2.50 (MyODBC 2.50)连接方式 1.本地数据库连接Driver={MySQL};Server=localhost;Option=16834; ...

  8. Dart语法基础

    hello world // Define a function. printNumber(num aNumber) { print('The number is $aNumber.'); // Pr ...

  9. vue.js2.0:如何搭建开发环境及构建项目

    1,安装node.js Node.js官网:https://nodejs.org/en/ 进入Node.js官网,选择下载并安装Node.js.安装过程只需要点击“下一步”即可, 如下图,非常简单. ...

  10. C# Web开发中弹出对话框的函数[转载]

    public void Alert(string str_Message) { ClientScriptManager scriptManager =((Page)System.Web.HttpCon ...