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. 学习Swift的点点滴滴

    1.类型标注 之前不知道为啥别人写的Swift语言的时候,定义常量或者变量的格式是 常量: let 常量名: 常量类型 = 常量值  或者 变量: var 变量名: 变量类型 = 初始值 原来书上有记 ...

  2. JVM-操作码助记符

    整理如下,用于以后查找: Opcode Mnemonics Note Constants 0x00 nop 无动作 0x01 aconst_null 把 null 推到操作数栈 0x02 iconst ...

  3. SQL Server 监控统计阻塞脚本信息

        数据库产生阻塞(Blocking)的本质原因 :SQL语句连续持有锁的时间过长 ,数目过多, 粒度过大.阻塞是事务隔离带来的副作用,它是不可避免的,而且是一个数据库系统常见的现象. 但是阻塞的 ...

  4. Oracle 11g 单实例安装文档

    这里介绍在Red Hat Enterprise Linux Server release 5.7 (Tikanga)下安装ORACLE 11.2.0.1.0的过程,本文仅仅是为了写这样安装指导文档而整 ...

  5. 【转】最牛B的编码套路

    最近,我大量阅读了Steve Yegge的文章.其中有一篇叫“Practicing Programming”(练习编程),写成于2005年,读后令我惊讶不已: 与你所相信的恰恰相反,单纯地每天埋头于工 ...

  6. hdfs client access the hdfs cluster not in one domain

    https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/HdfsMultihoming.html#Clients_u ...

  7. 帆软报表FineReport中数据连接之Websphere配置JNDI连接

    以oracle9i数据源制作的模板jndi.cpt为例来说明如何在FineReport中的Websphere配置JNDI连接.由于常用服务器的JNDI驱动过大,帆软报表FineReport中没有自带, ...

  8. 洛谷练习P2279 P1346

    题目描述 2020年,人类在火星上建立了一个庞大的基地群,总共有n个基地.起初为了节约材料,人类只修建了n-1条道路来连接这些基地,并且每两个基地都能够通过道路到达,所以所有的基地形成了一个巨大的树状 ...

  9. CH Round #72树洞[二分答案 DFS&&BFS]

    树洞 CH Round #72 - NOIP夏季划水赛 描述 在一片栖息地上有N棵树,每棵树下住着一只兔子,有M条路径连接这些树.更特殊地是,只有一棵树有3条或更多的路径与它相连,其它的树只有1条或2 ...

  10. Java 链表

    按链表的组织形式分有ArrayList和LinkList两种.ArrayList内部其实是用数组的形式实现链表,比较适合链表大小确定或较少对链表进行增删操作的情况,同时对每个链表节点的访问时间都是co ...