SAM+LCT维护parent tree版本

虽然说子树维护那套理论需要ETT

不过parent tree的根是固定的,所以用lct加一些奇怪的乱搞就行了

//随手拖个SAM的板子和LCT的板子,然后再加几句话就写完了【手动滑稽

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#define ll long long
#define N 1200006 using namespace std;
struct LinkCutTree{
#define ls(a) (t[a].c[0])
#define rs(a) (t[a].c[1])
struct LCTnode{
int c[2],fa;
int sum,tag;
} t[N];
void newnode(int x,int value){
ls(x)=rs(x)=t[x].fa=t[x].tag=0;
t[x].sum=value;
}
void Add(int x,int delta){
if (!x) return;
t[x].sum+=delta;t[x].tag+=delta;
}
int f(int x){return (ls(t[x].fa)!=x)*(1-2*(rs(t[x].fa)!=x));}
void PushDown(int x){
if (t[x].tag){
Add(ls(x),t[x].tag);
Add(rs(x),t[x].tag);
t[x].tag=0;
}
}
void rotate(int x){
int y=t[x].fa,z=t[y].fa,k=f(x),fz=f(y);
if (fz>=0) t[z].c[fz]=x;
t[y].c[k]=t[x].c[k^1];t[x].c[k^1]=y;
t[t[y].c[k]].fa=y;t[x].fa=z;t[y].fa=x;
}
int stack[N],top;
void splay(int x){
top=0;stack[top++]=x;
for (int i=x;f(i)>=0;i=t[i].fa) stack[top++]=t[i].fa;
while (top) PushDown(stack[--top]);
for (;f(x)>=0;rotate(x))
if (f(t[x].fa)==f(x)) rotate(t[x].fa);
else if (f(t[x].fa)>=0) rotate(x);
}
void access(int x){
for (int son=0;x;son=x,x=t[x].fa)
splay(x),rs(x)=son;
}
void link(int u,int f){
access(f);splay(f);Add(f,t[u].sum);
t[u].fa=f;
}
void cut(int u){
access(u);splay(u);Add(ls(u),-t[u].sum);
ls(u)=t[ls(u)].fa=0;
}
int getsum(int u){
splay(u);return t[u].sum;
}
} pt; struct SAM{
struct SAMnode{
int par,mx,go[26];
SAMnode(){}
SAMnode(int _mx):par(0),mx(_mx){
memset(go,0,sizeof(go));
}
} t[N];
int last,size;
int newnode(int _mx,int value){
t[++size]=SAMnode(_mx);
pt.newnode(size,value);
return size;
}
void clear(){size=0;last=newnode(0,0);}
void extend(char c){
c-='A';
int p=last,np=newnode(t[p].mx+1,1);
for (;p&&!t[p].go[c];p=t[p].par) t[p].go[c]=np;
if (!p) t[np].par=1,pt.link(np,1);
else{
int q=t[p].go[c];
if (t[p].mx+1==t[q].mx) t[np].par=q,pt.link(np,q);
else{
int nq=newnode(t[p].mx+1,0);
memcpy(t[nq].go,t[q].go,sizeof(t[q].go));
t[nq].par=t[q].par;pt.link(nq,t[q].par);
t[np].par=nq;pt.link(np,nq);
pt.cut(q);t[q].par=nq;pt.link(q,nq);
for (;p&&t[p].go[c]==q;p=t[p].par) t[p].go[c]=nq;
}
}
last=np;
}
int solve(char *s){
int p=1;
for (int i=0;p&&s[i];++i) p=t[p].go[s[i]-'A'];
if (!p) return 0;
return pt.getsum(p);
}
} sam; void decode(char *s,int mask){
int l=strlen(s);
for (int i=0;i<l;++i){
mask=(mask*131+i)%l;
swap(s[i],s[mask]);
}
} char st[N],op[10];
int main(){
int Q;scanf("%d%s",&Q,st);
sam.clear();
for (int i=0;st[i];++i) sam.extend(st[i]);
int mask=0,res;
while (Q--){
scanf("%s%s",op,st);
decode(st,mask);
if (op[0]=='Q'){
printf("%d\n",res=sam.solve(st));
mask^=res;
}
else for (int i=0;st[i];++i) sam.extend(st[i]);
}
return 0;
}

  

bzoj2555: SubString的更多相关文章

  1. BZOJ2555 SubString【SAM + Link Cut Tree】

    BZOJ2555. SubString 要求在线询问一个串在原串中出现的次数,并且可以在原串末尾添加字符串 如果没有修改的话,考虑建出\(parent\)树之后统计每个\(endpos\)节点的\(r ...

  2. [BZOJ2555]SubString LCT+后缀自动机

    2555: SubString Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 3253  Solved: 975[Submit][Status][Di ...

  3. BZOJ2555——SubString

    0.题目很短,就不概括了 给你一个字符串init,要求你支持两个操作 (1):在当前字符串的后面插入一个字符串 (2):询问字符串s在当前字符串中出现了几次?(作为连续子串) 你必须在线支持这些操作. ...

  4. 2019.03.01 bzoj2555: SubString(sam+lct)

    传送门 题意简述: 要求在线支持两个操作 (1):在当前字符串的后面插入一个字符串 (2):询问字符串s在当前字符串中出现了几次?(作为连续子串) 思路: 考虑用lctlctlct来动态维护samsa ...

  5. bzoj2555: SubString sam+lct

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

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

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

  7. bzoj千题计划285:bzoj2555: SubString

    http://www.lydsy.com/JudgeOnline/problem.php?id=2555 后缀自动机,用LCT维护parent树 一个串的出现次数 = parent 树 上 其所在状态 ...

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

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

  9. luogu5212/bzoj2555 substring(后缀自动机+动态树)

    对字符串构建一个后缀自动机. 每次查询的就是在转移边上得到节点的parent树中后缀节点数量. 由于强制在线,可以用动态树维护后缀自动机parent树的子树和. 注意一个玄学的优化:每次在执行连边操作 ...

随机推荐

  1. iOS 学习 - 20 UICollectionView 移动 Item ,类似背包

    有100个 item,数据源只有20个,只能在 20 个之间移动,防止 item 复用,出现 bug 方法一:苹果自带 //UICollectionViewDataSource- (BOOL)coll ...

  2. python-list tuple dict set

    1:删除一个列表末尾的元素 pop方法 >>> a [1, 'Jack', 2, 3, 2] >>> a.pop() >>> a [1, 'Jac ...

  3. Linux SSH登录慢案例分析

    手头有台Linux服务器ssh登录时超级慢,需要几十秒.其它服务器均没有这个问题.平时登录操作都默默忍了.今天终于忍不住想搞清楚到底什么原因.搜索了一下发现了很多关于ssh登录慢的资料,于是自己也学着 ...

  4. eAccelerator、memcached、xcache、APC 等四个加速扩展的区别

    折腾VPS的朋友,在安装好LNMP等Web运行环境后都会选择一些缓存扩展安装以提高PHP运行速度,常被人介绍的有eAccelerator.memcached.xcache.Alternative PH ...

  5. Android 实现网络多线程APK文件下载

    (转自:http://blog.csdn.net/mad1989/article/details/38421465) 实现原理 (1)首先获得下载文件的长度,然后设置本地文件的长度. (2)根据文件长 ...

  6. Web报表工具JS开发之日期校验

    在报表开发过程中,我们常常需要对查询界面进行日期校验.例如有两个参数:开始日期和结束日期,我们要校验的是:开始日期与结束日期不能为空,结束日期必须在开始日期之后以及结束日期必须在开始日期后的某个时间段 ...

  7. 你知道 Twitter,但你可能不知道它的 “成长模式” 和 “参与阶梯”

    当你为产品创建 “成长模式” 时,你需要回答以下关键问题(类Twitter产品:http://www.jinhusns.com/Products/Download/?type=xcj ): 目标:产品 ...

  8. MBTI-性格测试

  9. Linux环境导入*.sql文件出现数据库为空

    登录mysql命令: 导入.sql文件: 或者: mysql -h127.0.0.1 -uroot -p userDb < /home/user.sql  按回车键后输数据库的密码 导入成功后, ...

  10. 用MATLAB对信号做频谱分析

    1.首先学习下傅里叶变换的东西.学高数的时候老师只是将傅里叶变换简单的说了下,并没有深入的讲解.而现在看来,傅里叶变换似乎是信号处理的方面的重点只是呢,现在就先学习学习傅里叶变换吧. 上面这幅图在知乎 ...