[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


0

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\n",ans);
107             mask^=ans;
108         }
109     }
110 }
View Code

 

 

posted @ 2018-01-10 17:08  wls001  阅读(211)  评论(0编辑  收藏  举报