BZOJ2555:SubString(SAM,LCT)

Description

懒得写背景了,给你一个字符串init,要求你支持两个操作
(1):在当前字符串的后面插入一个字符串
(2):询问字符串s在当前字符串中出现了几次?(作为连续子串)
你必须在线支持这些操作。

Input

第一行一个数Q表示操作个数
第二行一个字符串表示初始字符串init
接下来Q行,每行2个字符串Type,Str
Type是ADD的话表示在后面插入字符串。
Type是QUERY的话表示询问某字符串在当前字符串中出现了几次。
为了体现在线操作,你需要维护一个变量mask,初始值为0 

    

读入串Str之后,使用这个过程将之解码成真正询问的串TrueStr。
询问的时候,对TrueStr询问后输出一行答案Result
然后mask=maskxorResult
插入的时候,将TrueStr插到当前字符串后面即可。
HINT:ADD和QUERY操作的字符串都需要解压
长度 <= 600000,询问次数<= 10000,询问总长度<= 3000000
新加数据一组--2015.05.20

Output

Sample Input

2
A
QUERY B
ADD BBABBBBAAB

Sample Output

0

Solution

可以发现这个题如果不是多组询问的话,就是求SAM的right集合的大小的裸题
不过一边插入一边询问很显然是无法像原来一样等全部字符都插入后再排序求right集合大小的
不过根据right集合的定义,其实我们可以发现一个点的right集合大小就是子树的np节点的个数
这玩意儿只需要用LCT维护子树权值和就好了

Code

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #define N (1200000+1000)
  5 using namespace std;
  6 
  7 int Father[N],Son[N][2],Size[N],Si[N],Rev[N],R[N],T,mask;
  8 char s[N],opt[10];
  9 
 10 int Get(int x){return Son[Father[x]][1]==x;}
 11 int Is_root(int x){return Son[Father[x]][0]!=x && Son[Father[x]][1]!=x;}
 12 void Update(int x){Size[x]=Si[x]+Size[Son[x][0]]+Size[Son[x][1]]+R[x];}
 13 
 14 void Pushdown(int x)
 15 {
 16     if (x && Rev[x])
 17     {
 18         if (Son[x][0]) Rev[Son[x][0]]^=1;
 19         if (Son[x][1]) Rev[Son[x][1]]^=1;
 20         swap(Son[x][0],Son[x][1]);
 21         Rev[x]=0;
 22     }
 23 }
 24 
 25 void Rotate(int x)
 26 {
 27     int wh=Get(x);
 28     int fa=Father[x],fafa=Father[fa];
 29     if (!Is_root(fa)) Son[fafa][Son[fafa][1]==fa]=x;
 30     Son[fa][wh]=Son[x][wh^1]; Father[fa]=x;
 31     Son[x][wh^1]=fa; Father[x]=fafa;
 32     if (Son[fa][wh]) Father[Son[fa][wh]]=fa;
 33     Update(fa); Update(x);
 34 }
 35 
 36 void Push(int x){if (!Is_root(x)) Push(Father[x]); Pushdown(x);}
 37 void Splay(int x)
 38 {
 39     Push(x);
 40     for (int fa; !Is_root(x); Rotate(x))
 41         if (!Is_root(fa=Father[x]))
 42             Rotate(Get(fa)==Get(x)?fa:x);
 43 }
 44 
 45 void Access(int x)
 46 {
 47     for (int y=0; x; y=x,x=Father[x])
 48     {
 49         Splay(x);
 50         Si[x]+=Size[Son[x][1]]; Si[x]-=Size[y];
 51         Son[x][1]=y; Update(x);
 52     }
 53 }
 54 
 55 void Make_root(int x){Access(x); Splay(x); Rev[x]^=1;}
 56 int Find_root(int x){Access(x); Splay(x); while (Son[x][0]) x=Son[x][0]; return x;}
 57 void Link(int x,int y){Make_root(x); Make_root(y); Father[x]=y; Si[y]+=Size[x]; Update(y);}
 58 void Cut(int x,int y){Make_root(x); Access(y); Splay(y); Son[y][0]=Father[x]=0; Update(y);}
 59 
 60 struct SAM
 61 {
 62     int fa[N],son[N][28],step[N];
 63     int p,q,np,nq,last,cnt;
 64     SAM(){last=++cnt;}
 65     
 66     void Insert(int x)
 67     {
 68         p=last; np=last=++cnt; step[np]=step[p]+1; R[np]=1; 
 69         while (p && !son[p][x]) son[p][x]=np,p=fa[p];
 70         if (!p) fa[np]=1,Link(np,1);
 71         else
 72         {
 73             q=son[p][x];
 74             if (step[p]+1==step[q]) fa[np]=q,Link(np,q);
 75             else
 76             {
 77                 nq=++cnt; step[nq]=step[p]+1;
 78                 memcpy(son[nq],son[q],sizeof(son[q]));
 79                 Link(nq,fa[q]); Cut(q,fa[q]); Link(q,nq); Link(np,nq); 
 80                 fa[nq]=fa[q]; fa[q]=fa[np]=nq;
 81                 while (son[p][x]==q) son[p][x]=nq,p=fa[p];
 82             }
 83         }
 84     }
 85     int Query(char s[])
 86     {
 87         Make_root(1);
 88         int now=1, len=strlen(s);
 89         for (int i=0; i<len; ++i)
 90             if (son[now][s[i]-'A']) now=son[now][s[i]-'A'];
 91             else return 0;
 92         Access(now); Splay(now);
 93         return Size[now]-Size[Son[now][0]];
 94     }
 95 }SAM;
 96 
 97 void Decode(char *s,int mask)
 98 {
 99     int len=strlen(s);
100     for(int i=0; i<len; ++i)
101     {
102         mask=(mask*131+i)%len;
103         swap(s[i],s[mask]);
104     }
105 }
106 
107 int main()
108 {
109     scanf("%d",&T);
110     scanf("%s",s);
111     int len=strlen(s);
112     for (int i=0; i<len; ++i)
113         SAM.Insert(s[i]-'A');
114     while (T--)
115     {
116         scanf("%s%s",opt,s);
117         int len=strlen(s);
118         Decode(s,mask);
119         if (opt[0]=='A')
120             for (int i=0; i<len; ++i)
121                 SAM.Insert(s[i]-'A');
122         else
123         {
124             int ans=SAM.Query(s);
125             printf("%d\n",ans);
126             mask^=ans;
127         }
128     }
129 }

 

posted @ 2018-07-27 16:13  Refun  阅读(214)  评论(0编辑  收藏  举报