天天看點

[BZOJ2555]SubString LCT+字尾自動機

2555: SubString

Time Limit: 30 Sec  Memory Limit: 512 MB

Submit: 3253  Solved: 975

[Submit][Status][Discuss]

Description

    懶得寫背景了,給你一個字元串init,要求你支援兩個操作

    (1):在目前字元串的後面插入一個字元串

    (2):詢問字元串s在目前字元串中出現了幾次?(作為連續子串)

    你必須線上支援這些操作。

Input

    第一行一個數Q表示操作個數

    第二行一個字元串表示初始字元串init

    接下來Q行,每行2個字元串Type,Str 

    Type是ADD的話表示在後面插入字元串。

    Type是QUERY的話表示詢問某字元串在目前字元串中出現了幾次。

    為了展現線上操作,你需要維護一個變量mask,初始值為0

    讀入串Str之後,使用這個過程将之解碼成真正詢問的串TrueStr。

    詢問的時候,對TrueStr詢問後輸出一行答案Result

    然後mask = mask xor Result  

    插入的時候,将TrueStr插到目前字元串後面即可。

HINT:ADD和QUERY操作的字元串都需要解壓

Output

Sample Input

2

A

QUERY B

ADD BBABBBBAAB

Sample Output

HINT

 40 % 的資料字元串最終長度 <= 20000,詢問次數<= 1000,詢問總長度<= 10000

100 % 的資料字元串最終長度 <= 600000,詢問次數<= 10000,詢問總長度<= 3000000

新加資料一組--2015.05.20

Source

Ctsc模拟賽By 潔妹

顯然我們要求目前子串子樹的字尾結束結點個數。

要線上實作,用lct維護sam

1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #include<cstdlib>
  5 #include<cmath>
  6 #include<algorithm>
  7 #define maxn 1200000
  8 using namespace std;
  9 int mask;
 10 char st[3000005];
 11 string chars;
 12 void gets(int mask) {
 13     scanf("%s",st);
 14     chars=st;
 15     for(int j=0;j<chars.length();j++) {
 16         mask=(mask*131+j)%chars.length();
 17         char t=chars[j];
 18         chars[j]=chars[mask];
 19         chars[mask]=t;
 20     }
 21 }
 22 struct data {
 23     int last,cnt;
 24     int son[maxn][26],link[maxn],step[maxn];
 25     data() {last=cnt=1;}
 26     struct lct {
 27         int fa[maxn],s[maxn][2],v[maxn],tag[maxn];
 28         bool isroot(int x) {return s[fa[x]][1]!=x&&s[fa[x]][0]!=x;}
 29         void add(int x,int y){if(x) v[x]+=y,tag[x]+=y;}
 30         void pushdown(int x) {
 31             if(tag[x]) {
 32                 add(s[x][0],tag[x]);add(s[x][1],tag[x]);
 33                 tag[x]=0;
 34             }
 35         }
 36         void push(int x) {
 37             if(!isroot(x)) push(fa[x]);
 38             pushdown(x);
 39         }
 40         void rorate(int x) {
 41             int y=fa[x],z=fa[y];
 42             bool l=(s[y][1]==x),r=l^1;
 43             if(!isroot(y)) s[z][s[z][1]==y]=x;
 44             fa[x]=z;fa[y]=x;s[y][l]=s[x][r];
 45             fa[s[x][r]]=y;s[x][r]=y;
 46         }
 47         void splay(int x) {
 48             push(x);
 49             while(!isroot(x)) {
 50                 int y=fa[x],z=fa[y];
 51                 if(!isroot(y)) {
 52                     if(s[y][0]==x^s[z][0]==y) rorate(x);
 53                     else rorate(y);
 54                 }
 55                 rorate(x);
 56             }
 57         }
 58         void access(int x) {for(int t=0;x;t=x,x=fa[x]) {splay(x);s[x][1]=t;}}
 59         void link(int x,int y) {fa[x]=y;access(y);splay(y);add(y,v[x]);}
 60         void cut(int x) {access(x);splay(x);add(s[x][0],-v[x]);s[x][0]=fa[s[x][0]]=0;}
 61     }t;
 62     void extend(int c) {
 63         int p=last,np=last=++cnt;step[np]=step[p]+1;t.v[np]=1;
 64         while(p&&!son[p][c]) son[p][c]=np,p=link[p];
 65         if(!p) link[np]=1,t.link(np,1);
 66         else {
 67             int q=son[p][c];
 68             if(step[q]==step[p]+1) link[np]=q,t.link(np,q);
 69             else {
 70                 int nq=++cnt;
 71                 memcpy(son[nq],son[q],sizeof(son[q]));
 72                 link[nq]=link[q];t.link(nq,link[q]);
 73                 link[q]=link[np]=nq;
 74                 t.cut(q);t.link(np,nq);t.link(q,nq);
 75                 step[nq]=step[p]+1;
 76                 while(son[p][c]==q&&p) son[p][c]=nq,p=link[p];
 77             }
 78         }
 79     }
 80     void add() {
 81         gets(mask);
 82         int l=chars.length();
 83         for(int i=0;i<l;i++) extend(chars[i]-'A');
 84     }
 85     int query() {
 86         gets(mask);
 87         int p=1,l=chars.length();
 88         for(int i=0;i<l;i++) {
 89             p=son[p][chars[i]-'A'];if(!p) return 0;
 90         }
 91         t.splay(p);
 92         return t.v[p];
 93     }
 94 }sam;
 95 int main() {
 96     int Q;scanf("%d",&Q);
 97     scanf("%s",st+1);
 98     int len=strlen(st+1);
 99     for(int i=1;i<=len;i++) sam.extend(st[i]-'A');
100     while(Q--) {
101         char s[10];
102         scanf("%s",s);
103         if(s[0]=='A') sam.add();
104         else {
105             int ans=sam.query();
106             printf("%d
",ans);
107             mask^=ans;
108         }
109     }
110 }      

View Code