【BZOJ2555】SubString

题面

http://darkbzoj.tk/problem/2555

题解

$LCT$ 维护子树权值和。

注意 $makeroot(x)$ 是真的 $makeroot$。(能看懂的人应该都看懂了)

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define ri register int
#define N 600050
using namespace std;

int mask;
int q;
char s[N],s0[N];
char tmp[N];
int cnt[N<<1];

void trans(int mask) {
  int n=strlen(s);
  for (ri i=0;i<n;i++) {
    mask=(mask*131+i)%n;
    swap(s[i],s[mask]);
  }
}

struct LinkCutTree {
  int sum[N<<1],sumi[N<<1],ch[N<<1][2];
  int fa[N<<1];
  bool rev[N<<1];
  int stk[N<<1],top;
  
  bool notroot(int x) {
    return ch[fa[x]][0]==x || ch[fa[x]][1]==x;
  }
  bool opt(int x) {
    return ch[fa[x]][1]==x;
  }
  void update(int x) {
    sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+sumi[x]+cnt[x];
  }
  void pushr(int x) {
    if (!rev[x]) return;
    rev[x]=0;
    swap(ch[x][0],ch[x][1]);
    if (ch[x][0]) rev[ch[x][0]]^=1;
    if (ch[x][1]) rev[ch[x][1]]^=1;
  }
  
  void rotate(int x) {
    //printf("ROTATE %d\n",x);
    int y=fa[x],z=fa[y],s=opt(x),w=ch[x][1^s];
    fa[x]=z; if (notroot(y)) ch[z][opt(y)]=x;
    if (w) fa[w]=y; ch[y][s]=w;
    ch[x][1^s]=y; fa[y]=x;
    update(y); update(x);
  }
  
  void splay(int x) {
    //printf("SPLAY %d\n",x);
    top=1; int y=x;
    while (notroot(y)) stk[top++]=y,y=fa[y]; stk[top]=y;
    while (top) pushr(stk[top]),top--;
    while (notroot(x)) {
      if (!notroot(fa[x])) rotate(x);
      else {
        if (opt(x)==opt(fa[x])) rotate(fa[x]); else rotate(x);
        rotate(x);
      }
    }
  }
  
  void access(int x) {
    //printf("ACCESS %d\n",x);
    int y=0;
    while (x) {
      splay(x);
      sumi[x]+=sum[ch[x][1]];
      sumi[x]-=sum[ch[x][1]=y];
      update(x);
      y=x; x=fa[x];
    }
  }
  
  void makeroot(int x) {
    //printf("MAKEROOT %d\n",x);
    access(x); splay(x);
    rev[x]^=1; pushr(x);
  }
  
  void link(int x,int ff) {
    //printf("LINK %d %d\n",x,ff);
    makeroot(x);
    access(ff);
    splay(ff);
    fa[x]=ff;
    sumi[ff]+=sum[x];
    update(ff);
  }
  
  void cut(int x,int ff) {
    //printf("CUT %d %d\n",x,ff);
    makeroot(ff);
    access(x);
    splay(x);
    ch[x][opt(ff)]=fa[ff]=0;
    update(x);
  }
  
  int query(int x) {
    if (!x) return 0;
    makeroot(1);
    access(x);
    return sum[x]-sum[ch[x][0]]-sum[ch[x][1]];
  }
} lct;

struct SuffixAutoMachine {
  int len[N<<1],ff[N<<1];
  int ch[N<<1][26];
  int ton[N<<1],a[N<<1];
  int aaa[N<<1];
  int las,tot;
  inline void init() {tot=las=1;}
  inline void extend(int c) {
    int p=las,np=++tot; las=np;
    cnt[np]=1;
    len[np]=len[p]+1;
    while (p && !ch[p][c]) ch[p][c]=np,p=ff[p];
    if (!p) ff[np]=1;
    else {
      int q=ch[p][c];
      if (len[q]==len[p]+1) ff[np]=q;
      else {
        int nq=++tot;
        for (ri i=0;i<26;i++) ch[nq][i]=ch[q][i]; ff[nq]=ff[q]; len[nq]=len[p]+1;
        lct.link(nq,ff[nq]);
        lct.cut(q,ff[q]);
        ff[np]=ff[q]=nq;
        lct.link(q,ff[q]);
        while (p && ch[p][c]==q) ch[p][c]=nq,p=ff[p];
      }
    }
    lct.link(np,ff[np]);
  }
  int find() {
    int now=1;
    for (ri i=0,l=strlen(s);i<l;i++) now=ch[now][s[i]-'A'];
    return now;
  }
} sam;

int main(){
  scanf("%d",&q);
  scanf("%s",s); sam.init();
  for (ri i=0,l=strlen(s);i<l;i++) sam.extend(s[i]-'A');
  for (ri j=1;j<=q;j++) {
    scanf("%s",s0);
    if (s0[0]=='Q') {
      scanf("%s",s); trans(mask);
      int p=sam.find();
      int ans2=lct.query(p);
      printf("%d\n",ans2);
      mask^=ans2;
    }
    else {
      scanf("%s",s); trans(mask);
      for (ri i=0,l=strlen(s);i<l;i++) sam.extend(s[i]-'A');
    }
  }
}

 

posted @ 2019-07-31 21:26  HellPix  阅读(133)  评论(0编辑  收藏  举报