Luogu P5212 SubString

\(SAM\) + \(LCT\) 维护 \(parent树\)

每次插入一个点对应修改 \(LCT\) 并链加,相当于在链上的 \(\rm endpos\) 中添加一个新的位置。

匹配就在 \(SAM\) 上跑即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#define R register int
using namespace std;
namespace Luitaryi {
inline int g() { R x=0,f=1;
  register char s; while(!isdigit(s=getchar())) f=s=='-'?-1:f;
  do x=x*10+(s^48); while(isdigit(s=getchar())); return x*f;
} const int N=1200010;
namespace LCT {
  int fa[N],ch[N][2],sum[N],add[N],stk[N];
  bool tg[N];
  #define ls(x) (ch[x][0])
  #define rs(x) (ch[x][1])
  #define rev(x) (swap(ls(x),rs(x)),tg[x]^=1)
  inline bool isroot(int x) {return ls(fa[x])!=x&&rs(fa[x])!=x;}
  inline void spread(int x) {
    if(tg[x]) {
      if(ls(x)) rev(ls(x));
      if(rs(x)) rev(rs(x));
      tg[x]=0;
    }
    if(add[x]) {
      if(ls(x)) sum[ls(x)]+=add[x],add[ls(x)]+=add[x];
      if(rs(x)) sum[rs(x)]+=add[x],add[rs(x)]+=add[x];
      add[x]=0;
    }
  }
  inline void rot(int x) {
    R y=fa[x]; R d=ch[y][1]==x;
    if(!isroot(y)) ch[fa[y]][ch[fa[y]][1]==y]=x;
    fa[x]=fa[y],fa[ch[y][d]=ch[x][d^1]]=y;
    fa[ch[x][d^1]=y]=x;
  }
  inline void Splay(int x) {
    R y=x,top=0; stk[++top]=y;
    while(!isroot(y)) stk[++top]=y=fa[y];
    while(top) spread(stk[top--]);
    while(!isroot(x)) {
      y=fa[x];
      if(!isroot(y)) rot((ch[fa[y]][1]==y)==(ch[y][1]==x)?y:x);
      rot(x);
    }
  }
  inline void acc(int x) {for(R y=0;x;x=fa[y=x]) Splay(x),rs(x)=y;}
  inline void mrt(int x) {acc(x),Splay(x),rev(x);}
  inline int frt(int x) {
    acc(x),Splay(x);
    while(ls(x)) spread(x),x=ls(x);
    Splay(x); return x;
  }
  inline void split(int x,int y) {mrt(x),acc(y),Splay(x);}
  inline void link(int x,int y) {Splay(y),fa[x]=y;}
  inline void cut(int x,int y) {split(x,y),fa[y]=rs(x)=0;}
} using namespace LCT;
struct SAM {
  int lst,tot;
  int fa[N],c[N][26],len[N];
  SAM() {lst=tot=1;}
  inline void add(int ch) {
    R p=lst,np=lst=++tot;
    len[np]=len[p]+1;
    while(p&&!c[p][ch]) c[p][ch]=np,p=fa[p];
    if(!p) {
      fa[np]=1,link(np,fa[np]);
      split(1,np),++sum[1],++LCT::add[1];
      return ;
    }
    R q=c[p][ch];
    if(len[q]==len[p]+1) {
      fa[np]=q,link(np,fa[np]);
      split(1,np),++sum[1],++LCT::add[1];
      return ;
    }
    R nq=++tot;
    memcpy(c[nq],c[q],26<<2);
    cut(q,fa[q]);
    fa[nq]=fa[q],len[nq]=len[p]+1;
    fa[np]=fa[q]=nq;
    link(nq,fa[nq]),link(np,fa[np]),link(q,fa[q]);
    Splay(q),sum[nq]=sum[q];
    while(p&&c[p][ch]==q) c[p][ch]=nq,p=fa[p];
    split(1,np),++sum[1],++LCT::add[1];
  }
}s1;
int mask;
string chars;
char S[3000010],s[N];
inline void dec(int mask) {
    scanf("%s",S);
    chars=S;
    for(R j=0,lim=chars.size();j<lim;j++) {
        mask=(mask*131+j)%lim;
        register char tem=chars[j];
        chars[j]=chars[mask];
        chars[mask]=tem;
    }
}
int n,m;
inline void main() {
  m=g(),scanf("%s",s+1);
  n=strlen(s+1);
  for(R i=1;i<=n;++i)   
    s1.add(s[i]-'A');
  register char op[6];
  while(m--) {
    scanf("%s",op);
    if(op[0]=='A') {
      dec(mask);
      for(R i=0,lim=chars.size();i<lim;++i)
        s1.add(chars[i]-'A');
    } else {
      dec(mask);
      R p=1;
      for(R i=0,lim=chars.size();i<lim;++i) {
        p=s1.c[p][chars[i]-'A'];
        if(!p) break;
      } if(!p) puts("0");
      else Splay(p),
        printf("%d\n",sum[p]),mask^=sum[p];
    }
  }
}
} signed main() {Luitaryi::main(); return 0;}

2020.01.10

猜你喜欢

转载自www.cnblogs.com/Jackpei/p/12177570.html
今日推荐