雯舞

Love three things int he world -- Manchery

[后缀自动机 LCT] BZOJ 2555 SubString

构建后缀自动机 parent树会改变形态 这样|right(x)|也会发生变化
我们用LCT大力维护一发就好了

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;

inline char nc(){
  static char buf[100000],*p1=buf,*p2=buf;
  if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
  return *p1++;
}

inline void read(int &x){
  char c=nc(),b=1;
  for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
  for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

inline int read(char *s){
  char c=nc(); int len=0;
  for (;!(c>='A' && c<='Z');c=nc()) if (c==EOF) return 0;
  for (;c>='A' && c<='Z';s[++len]=c,c=nc()); s[++len]=0; return len-1;
}

const int N=1200005;

struct Splay{  
#define ls ch[x][0]  
#define rs ch[x][1]  
  int val[N],ch[N][2],fat[N],add[N];  
  inline int dir(int x){return ch[fat[x]][1]==x;}  
  inline int isroot(int x){return ch[fat[x]][0]!=x&&ch[fat[x]][1]!=x;}  
  inline void mark(int x,int v){add[x]+=v,val[x]+=v;}  
  inline void pushdown(int x){  
    if (add[x]!=0){  
      if (ls) mark(ls,add[x]);  
      if (rs) mark(rs,add[x]);  
      add[x]=0;  
    }  
  }  
  void relax(int x){if (!isroot(x)) relax(fat[x]);pushdown(x);}  
  void rotate(int x){  
    int y=fat[x],z=fat[y],nx=dir(x),ny=dir(y),isrt=isroot(y);  
    fat[ch[x][!nx]]=y,ch[y][nx]=ch[x][!nx];  
    fat[x]=z;if (!isrt) ch[z][ny]=x;  
    fat[y]=x,ch[x][!nx]=y;  
  }  
  void splay(int x){  
    relax(x);  
    while (!isroot(x)){  
      int y=fat[x];  
      if (isroot(y)) rotate(x);  
      else if (dir(x)==dir(y)) rotate(y),rotate(x);  
      else rotate(x),rotate(x);  
    }  
  }  
  void access(int x){  
    for (int p=0;x;x=fat[x])  
      splay(x),rs=p,p=x;  
  }  
  void link(int x,int f){  
    fat[x]=f,access(f),splay(f),mark(f,val[x]);  
  }  
  void cut(int x){  
    access(x),splay(x),mark(ls,-val[x]);  
    fat[ls]=0,ls=0;  
  }  
#undef ls  
#undef rs  
}LCT;

struct state{
  int len,link,next[26];
}st[N];
int ncnt,last;

inline void Extend(char c){
  int cur=++ncnt,p; c-='A';
  st[cur].len=st[last].len+1; LCT.val[cur]=1;
  for (p=last;p!=-1 && !st[p].next[c];p=st[p].link)
    st[p].next[c]=cur;
  if (p==-1)
    st[cur].link=1,LCT.link(cur,1);
  else{
    int q=st[p].next[c];
    if (st[q].len==st[p].len+1)
      st[cur].link=q,LCT.link(cur,q);
    else{
      int nq=++ncnt;
      st[nq].len=st[p].len+1;
      st[nq].link=st[q].link;
      LCT.cut(q); LCT.link(nq,st[q].link);
      memcpy(st[nq].next,st[q].next,sizeof(st[q].next));
      for (;p!=-1 && st[p].next[c]==q;p=st[p].link)
    st[p].next[c]=nq;
      st[q].link=st[cur].link=nq;
      LCT.link(q,nq); LCT.link(cur,nq);
    }
  }
  last=cur;
}

int n; char S[N];

inline void decode(int mask){  
  for (int i=1;i<=n;i++){  
    mask=(mask*131+i-1)%n;  
    swap(S[i],S[mask+1]);
  }  
}  

int main(){
  int Q,mask=0; char order[15];
  freopen("t.in","r",stdin);
  freopen("t.out","w",stdout);
  read(Q); n=read(S);
  ncnt=last=1; st[1].link=-1;
  for (int i=1;i<=n;i++)
    Extend(S[i]);
  while (Q--){
    read(order); n=read(S); decode(mask);
    if (order[1]=='A'){
      for (int i=1;i<=n;i++)
    Extend(S[i]);
    }else{
      int p=1,ans=-1;
      for (int i=1;i<=n;i++){
    if (!st[p].next[S[i]-'A']) { ans=0; break; }
    p=st[p].next[S[i]-'A'];  
      }
      if (ans==-1)
    LCT.splay(p),ans=LCT.val[p];  
      printf("%d\n",ans); 
      mask^=ans;
    }
  }
  return 0;
}
阅读更多
版权声明:本文为博主原创文章,未经博主允许随意转载。 https://blog.csdn.net/u014609452/article/details/54767586
个人分类: 后缀自动机 LCT
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

不良信息举报

[后缀自动机 LCT] BZOJ 2555 SubString

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭