题意:懒得写背景了,给你一个字符串init,要求你支持两个操作

(1):在当前字符串的后面插入一个字符串

(2):询问字符串s在当前字符串中出现了几次?(作为连续子串)

你必须在线支持这些操作。

题解:可以想到用sam很好维护某个字符串在当前字符串中出现了几次,插入也直接add就好了,但是我们不能每次查询的时候topo然后更新sz,可以想到是不是可以每次加入一个新字符时,不断的向fa上跳,直到跳到根为止,但是这样最坏也是O(n)的,我们考虑怎么快速维护sam的fa树加边删边,更新链权值,很明显就能想到lct,lct打lazy标记更新链即可,sam中更新fa的时候在lct上加删边就好了,查询就splay到当前splay树的根,然后求val

注意:新建nq时,要把q的sz赋值给sz[nq]

/**************************************************************
Problem: 2555
User: walfy
Language: C++
Result: Accepted
Time:20820 ms
Memory:177688 kb
****************************************************************/ //#pragma GCC optimize(2)
//#pragma GCC optimize(3)
//#pragma GCC optimize(4)
//#pragma GCC optimize("unroll-loops")
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include<bits/stdc++.h>
#define fi first
#define se second
#define db double
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 1000000007
#define ld long double
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
//#define cd complex<double>
#define ull unsigned long long
#define base 1000000000000000000
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define fin freopen("a.txt","r",stdin)
#define fout freopen("a.txt","w",stdout)
#define fio ios::sync_with_stdio(false);cin.tie(0)
template<typename T>
inline T const& MAX(T const &a,T const &b){return a>b?a:b;}
template<typename T>
inline T const& MIN(T const &a,T const &b){return a<b?a:b;}
inline void add(ll &a,ll b){a+=b;if(a>=mod)a-=mod;}
inline void sub(ll &a,ll b){a-=b;if(a<0)a+=mod;}
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline ll qp(ll a,ll b){ll ans=1;while(b){if(b&1)ans=ans*a%mod;a=a*a%mod,b>>=1;}return ans;}
inline ll qp(ll a,ll b,ll c){ll ans=1;while(b){if(b&1)ans=ans*a%c;a=a*a%c,b>>=1;}return ans;} using namespace std; const double eps=1e-8;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int N=600000+10,maxn=3000000+10,inf=0x3f3f3f3f; char s[maxn];
struct LCT{
int fa[N<<1],ch[N<<1][2],rev[N<<1],sz[N<<1],q[N<<1],val[N<<1],add[N<<1];
inline bool isroot(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
inline void pushup(int x)
{
sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1;
}
inline void pushdown(int x)
{
if(rev[x])
{
rev[x]=0;swap(ch[x][0],ch[x][1]);
rev[ch[x][0]]^=1,rev[ch[x][1]]^=1;
}
if(add[x])
{
if(ch[x][0])val[ch[x][0]]+=add[x],add[ch[x][0]]+=add[x];
if(ch[x][1])val[ch[x][1]]+=add[x],add[ch[x][1]]+=add[x];
add[x]=0;
}
}
inline void Rotate(int x)
{
int y=fa[x],z=fa[y],l,r;
if(ch[y][0]==x)l=0,r=l^1;
else l=1,r=l^1;
if(!isroot(y))
{
if(ch[z][0]==y)ch[z][0]=x;
else ch[z][1]=x;
}
fa[x]=z;fa[y]=x;fa[ch[x][r]]=y;
ch[y][l]=ch[x][r];ch[x][r]=y;
pushup(y);
}
inline void splay(int x)
{
int top=1;q[top]=x;
for(int i=x;!isroot(i);i=fa[i])q[++top]=fa[i];
for(int i=top;i;i--)pushdown(q[i]);
while(!isroot(x))
{
int y=fa[x],z=fa[y];
if(!isroot(y))
{
if((ch[y][0]==x)^(ch[z][0]==y))Rotate(x);
else Rotate(y);
}
Rotate(x);
}
pushup(x);
}
inline void access(int x){for(int y=0;x;y=x,x=fa[x])splay(x),ch[x][1]=y,pushup(x);}
inline void makeroot(int x){access(x),splay(x),rev[x]^=1;}
inline int findroot(int x){access(x),splay(x);while(ch[x][0])x=ch[x][0];return x;}
inline void split(int x,int y){makeroot(x),access(y),splay(y);}
inline void cut(int x,int y){split(x,y);if(ch[y][0]==x)ch[y][0]=0,fa[x]=0;}
inline void link(int x,int y){makeroot(x),fa[x]=y,splay(x);}
}lct;
struct SAM{
int last,cnt;
int ch[N<<1][26],fa[N<<1],l[N<<1],sz[N<<1];
void ins(int c){
int p=last,np=++cnt;last=np;l[np]=l[p]+1;
for(;p&&!ch[p][c];p=fa[p])ch[p][c]=np;
if(!p)fa[np]=1,lct.link(np,1);
else
{
int q=ch[p][c];
if(l[p]+1==l[q])fa[np]=q,lct.link(np,q);
else
{
int nq=++cnt;l[nq]=l[p]+1;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
lct.link(nq,fa[q]);lct.link(np,nq);
lct.cut(q,fa[q]);lct.link(q,nq);
fa[nq]=fa[q];fa[q]=fa[np]=nq;
lct.splay(nq);lct.splay(q);
lct.val[nq]=lct.val[q];
for(;ch[p][c]==q;p=fa[p])ch[p][c]=nq;
}
}
lct.split(np,1);
lct.add[1]++,lct.val[1]++;
// sz[np]=1;
// for(;np;np=fa[np])sz[np]++;
}
void build(){
int len=strlen(s);
last=cnt=1;
for(int i=0;i<len;i++)ins(s[i]-'A');
}
int cal()
{
int len=strlen(s);
int now=1;
for(int i=0;i<len;i++)
{
if(ch[now][s[i]-'A'])now=ch[now][s[i]-'A'];
else return 0;
}
lct.splay(now);
return lct.val[now];
}
}sam;
void change(int mask)
{
int len=strlen(s);
for(int i=0; i<len; i++)
{
mask=(mask*131+i)%len;
swap(s[mask],s[i]);
}
}
int main()
{
int n;scanf("%d%s",&n,s);
sam.build();
int mask=0;
while(n--)
{
char op[10];
scanf("%s%s",op,s);
change(mask);
if(op[0]=='A')
{
int len=strlen(s);
for(int i=0;i<len;i++)sam.ins(s[i]-'A');
}
else
{
int ans=sam.cal();
mask^=ans;
printf("%d\n",ans);
}
}
return 0;
}
/********************
23
ABAAB
Q AA
Q A
A ABA
Q AB
Q B
Q A
A AAA
Q AA
Q A
Q AAA
********************/

bzoj2555: SubString sam+lct的更多相关文章

  1. BZOJ2555 SubString【SAM + Link Cut Tree】

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

  2. bzoj2555: SubString

    SAM+LCT维护parent tree版本 虽然说子树维护那套理论需要ETT 不过parent tree的根是固定的,所以用lct加一些奇怪的乱搞就行了 //随手拖个SAM的板子和LCT的板子,然后 ...

  3. 2019.03.01 bzoj2555: SubString(sam+lct)

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

  4. 【BZOJ 2555】 2555: SubString (SAM+LCT)

    2555: SubString Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 2548  Solved: 762 Description 懒得写背景了 ...

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

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

  6. bzoj 2555 SubString(SAM+LCT)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2555 [题意] 给定一个字符串,可以随时插入字符串,提供查询s在其中作为连续子串的出现 ...

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

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

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

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

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

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

随机推荐

  1. C# 中2个问号的作用。C#的??代表是什么意思

    https://www.cnblogs.com/gggg/p/5867412.html 变量定义中含有一个问号,意思是这个数据类型是NullAble类型的.(NullAble意思是可以为空) 变量定义 ...

  2. p3396 哈希冲突(暴力)

    想了好久,没想到优秀的解法,结果是个暴力大吃一静.jpg 分类讨论,预处理\(p\le \sqrt{n}\) 的情况,其他直接暴力,复杂度\(O(n \sqrt{n} )\) #include < ...

  3. (zhuan) Paper Collection of Multi-Agent Reinforcement Learning (MARL)

    this blog from: https://github.com/LantaoYu/MARL-Papers Paper Collection of Multi-Agent Reinforcemen ...

  4. promise对象的使用

    ES6中的promise的出现给我们很好的解决了回调地狱的问题,在使用ES5的时候,在多层嵌套回调时,写完的代码层次过多,很难进行维护和二次开发,ES6认识到了这点问题, 现在promise的使用,完 ...

  5. ngnix简介以及如何实现负载均衡原理

    1 负载均衡 先来简单了解一下什么是负载均衡,单从字面上的意思来理解就可以解释N台服务器平均分担负载,不会因为某台服务器负载高宕机而某台服务器闲置的情况.那么负载均衡的前提就是要有多台服务器才能实现, ...

  6. Autofac创建实例的方法总结

    1.InstancePerDependency 对每一个依赖或每一次调用创建一个新的唯一的实例.这也是默认的创建实例的方式. 2.InstancePerLifetimeScope 在一个生命周期域中, ...

  7. python学习 day017打卡 类与类之间的关系

    本节主要的内容: 1.依赖关系 2.关联关系,组合关系,聚合关系 3.继承关系,self到底是什么? 4.类中的特殊成员 一.类与类之间的依赖关系 在面向对象的世界中,类与类中存在以下关系: 1.依赖 ...

  8. _spellmod_aura_trigger

    一.spell.dbc做一个空光环 二.配置_spellmod_aura_trigger表 comment 备注 aura 光环ID,有此光环时,才会触发下面技能 linkSpell1-3 链接的技能 ...

  9. eclipse里安装SVN插件的两种方式

    eclipse里安装SVN插件,一般来说,有两种方式: 直接下载SVN插件,将其解压到eclipse的对应目录里 使用eclipse 里Help菜单的“Install New Software”,通过 ...

  10. String和常量池

    1.Java 会确保一个字符串常量只有一个拷贝 2.用new String() 创建的字符串不是常量,不能在编译期就确定,所以new String() 创建的字符串不放入常量池中,它们有自己的地址空间 ...