您的位置:首页 > 其它

BZOJ2555:SubString 后缀自动机 LCT

2017-01-04 10:43 363 查看
给你一个字符串init,要求你支持两个操作

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

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

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

字符串最终长度 <= 600000,询问次数<= 10000,询问总长度<= 3000000

一个子串出现的次数等于后缀自动机的parent树(也就是反串的后缀树)上这个串对应的节点集合内元素的数量。由parent树的性质可知,这个数量等于子树内反前缀节点的数量。因此对parent树维护LCT,每次新加一个节点后,将这个节点到根的路径size加一,查询时找到需要的节点用LCT查询size值即可。

需要注意的是,nq节点拷贝q节点时要连着size值一起复制。

#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
static char pool[158400000];
struct node
{
//LCT elements
node *s[2],*f;
int add,v;
inline char r(){return this==f->s[0]?0:this==f->s[1]?1:-1;}
inline void plus(int x=1){add+=x,v+=x;}
inline void down(){if(~r()) f->down();if(add){s[0]->plus(add),s[1]->plus(add),add=0;}}
inline void setson(node* p){p->f=p->pa=this;}
inline void cutf();
inline int size();
inline void mark();
//SAM elements
node *trans[26],*pa;
int d;
node(int dep=0);
inline void* operator new(size_t);
inline void copy(node *x)
{
v=x->v;
memcpy(trans,x->trans,sizeof trans);
}
}*nil=new node;
node::node(int dep):f(nil),add(0),v(0),trans(),pa(),d(dep){s[0]=s[1]=nil;}
inline void* node::operator new(size_t)
{
static node* s=(node*)pool;
static size_t t=-1;
return s+ ++t;
}
inline void rot(node *x)
{
static node *o,*y;
static char k;
k=x->r();if(k==-1) return;
k=!k;
o=x->f,y=x->s[k];
x->s[k]=o,o->s[!k]=y;
if(~(k=o->r())) o->f->s[k]=x;
x->f=o->f,o->f=x,y->f=o;
}
inline void splay(node *x)
{
x->down();
while(~x->r()) rot(x->r()==x->f->r()?x->f:x),rot(x);
}
inline void __access(node *x)
{
static node *y;
y=nil;
while(x!=nil)
{
splay(x);
x->s[1]=y;
y=x;
x=x->f;
}
}
inline void access(node *x)
{
__access(x),splay(x);
}
inline void chain_add(node *x)
{
access(x);
x->plus();
}
inline int getsum(node *x)
{
splay(x);
return x->v;
}
inline void cut(node *x)
{
access(x);
x->s[0]=x->s[0]->f=nil;
}
inline void node::mark()
{
chain_add(this);
}
inline int node::size()
{
return getsum(this);
}
inline void node::cutf()
{
cut(this);
}
struct sam
{
node *rt,*last;
sam():rt(new node),last(rt){}
inline void push_back(char c)
{
node *p,*q,*np,*nq;
c-='A';
p=last;
np=last=new node(p->d+1);
while(p&&!p->trans[c]) p->trans[c]=np,p=p->pa;
if(!p) {rt->setson(np);goto finish;}
q=p->trans[c];
if(p->d+1==q->d) {q->setson(np);goto finish;}
nq=new node(p->d+1);
q->pa->setson(nq);q->cutf();
nq->copy(q);
nq->setson(q);nq->setson(np);
while(p&&p->trans[c]==q) p->trans[c]=nq,p=p->pa;
finish:
np->mark();
}
inline size_t count(const char *s)
{
node *now=rt;
while(*s)
{
now=now->trans[(*s++)-'A'];
if(!now) return 0;
}
return now->size();
}
}tr;
inline void unzip(char *s,int mask)
{
int len=strlen(s);
for(int i=0;i<len;++i)
{
mask=(mask*131+i)%len;
char t=s[i];
s[i]=s[mask];
s[mask]=t;
}
}
char s[3000001],tp[6];
int q,mask=0;
int main()
{
scanf("%d",&q);
scanf("%s",s);
for(int i=0;s[i];++i)
tr.push_back(s[i]);
while(q--)
{
scanf("%s%s",tp,s);
unzip(s,mask);
if(*tp=='A')
{
for(int i=0;s[i];++i)
tr.push_back(s[i]);
}
else
{
size_t ans=tr.count(s);
mask^=ans;
printf("%u\n",ans);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: