BZOJ 2555 SubString 后缀自动机+LCT

Posted KKKorange的代码盒子

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 2555 SubString 后缀自动机+LCT相关的知识,希望对你有一定的参考价值。

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2555

 

题意概述:给出一个初始字符串,支持两种操作:1、在这个字符串后面接上一个字符串;2、询问一个字符串在当前串中出现的次数。强制在线。

 

你发现这个东西没有更新就是SAM裸题。。。。。

有更新?SAM里面没问题,但是我们需要维护每个状态的right集合大小以及parent树的形态,于是就来一发LCT。

然后你发现这么直接写巨慢。。。。再来你发现parent树的根始终没有变过(滑稽),所以就没有mroot之类的操作的必要了。

 

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cstdlib>
  5 #include<algorithm>
  6 #include<cmath>
  7 #include<queue>
  8 #include<set>
  9 #include<map>
 10 #include<vector>
 11 #include<cctype>
 12 using namespace std;
 13 const int MAXN=3000005;
 14 
 15 int Q,mask; char S[MAXN];
 16 struct Link_Cut_Tree{
 17     static const int maxn=1200005;
 18     int np,ch[maxn][2],fa[maxn],w[maxn],add[maxn];
 19     Link_Cut_Tree(){ np=0; }
 20     bool isrt(int x){ return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x; }
 21     void link(int x,int d,int y){ ch[x][d]=y,fa[y]=x; }
 22     void pushdown(int x){
 23         if(!add[x]) return;
 24         int lc=ch[x][0],rc=ch[x][1];
 25         if(lc) add[lc]+=add[x],w[lc]+=add[x];
 26         if(rc) add[rc]+=add[x],w[rc]+=add[x];
 27         add[x]=0;
 28     }
 29     void rot(int x){
 30         int y=fa[x],z=fa[y];
 31         pushdown(y); pushdown(x);
 32         int d=ch[y][0]==x;
 33         if(!isrt(y)) link(z,ch[z][1]==y,x); fa[x]=z;
 34         link(y,d^1,ch[x][d]);
 35         link(x,d,y);
 36     }
 37     void splay(int x){
 38         pushdown(x);
 39         while(!isrt(x)){
 40             int y=fa[x],z=fa[y];
 41             if(!isrt(y)) rot((ch[y][0]==x)==(ch[z][0]==y)?y:x);
 42             rot(x);
 43         }
 44     }
 45     void access(int x){
 46         int y=0;
 47         while(x){ splay(x); ch[x][1]=y,y=x,x=fa[x]; }
 48     }
 49     void Cut(int x,int y){ access(x); splay(y); fa[y]=0; }
 50     void update(int x){
 51         access(x); splay(x);
 52         add[x]++,w[x]++;
 53     }
 54     int val(int x){ splay(x); return w[x]; }
 55 }lct;
 56 struct Suffix_Automaton{
 57     static const int maxn=1200005;
 58     static const int sigma_sz=26;
 59     int sz,last,to[maxn][sigma_sz],mx[maxn],pa[maxn];
 60     Suffix_Automaton(){ sz=last=1; memset(to[1],0,sizeof(to[1])); }
 61     int newnode(){
 62         memset(to[++sz],0,sizeof(to[sz]));
 63         mx[sz]=pa[sz]=0;
 64         return sz;
 65     }
 66     void extend(int w){
 67         int p=last,np=newnode(); last=np;
 68         mx[np]=mx[p]+1;
 69         while(p&&!to[p][w]) to[p][w]=np,p=pa[p];
 70         if(!p){ pa[np]=1; lct.fa[np]=1; }
 71         else{
 72             int q=to[p][w];
 73             if(mx[q]==mx[p]+1){ pa[np]=q; lct.fa[np]=q; }
 74             else{
 75                 int nq=newnode(); mx[nq]=mx[p]+1;
 76                 memcpy(to[nq],to[q],sizeof(to[q]));
 77                 pa[nq]=pa[q]; lct.Cut(pa[q],q); lct.fa[nq]=pa[nq];
 78                 pa[q]=pa[np]=nq; lct.fa[q]=lct.fa[np]=nq; lct.w[nq]=lct.w[q];
 79                 while(p&&to[p][w]==q) to[p][w]=nq,p=pa[p];
 80             }
 81         }
 82         lct.update(np);
 83     }
 84     int find(char *s){
 85         int now=1,i=0,n=strlen(s);
 86         while(i<n){
 87             if(!to[now][s[i]-A]) return 0;
 88             now=to[now][s[i++]-A];
 89         }
 90         return now;
 91     }
 92 }sam;
 93 
 94 void _scanf(char *s)
 95 {
 96     int cnt=0;
 97     char c=getchar();
 98     while(!isalpha(c)) c=getchar();
 99     while(isalpha(c)) s[cnt++]=c,c=getchar();
100     s[cnt]=\0;
101 }
102 void data_in()
103 {
104     scanf("%d",&Q); _scanf(S);
105     int n=strlen(S);
106     for(int i=0;i<n;i++) sam.extend(S[i]-A);
107 }
108 void unzip(char *s,int m)
109 {
110     int n=strlen(s);
111     for(int i=0;i<n;i++)
112         m=(m*131+i)%n,swap(s[i],s[m]);
113 }
114 void work()
115 {
116     char op[10]; int ans,n,x;
117     for(int i=1;i<=Q;i++){
118         _scanf(op);_scanf(S);
119         unzip(S,mask);
120         if(op[0]==A){
121             n=strlen(S);
122             for(int i=0;i<n;i++) sam.extend(S[i]-A);
123         }
124         else if(op[0]==Q){
125             x=sam.find(S);
126             printf("%d\n",ans=!x?0:lct.val(x));
127             mask^=ans;
128         }
129     }
130 }
131 int main()
132 {
133     data_in();
134     work();
135     return 0;
136 }

 

以上是关于BZOJ 2555 SubString 后缀自动机+LCT的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ2555SubString 后缀自动机+LCT

bzoj 2555 SubString —— 后缀自动机+LCT

BZOJ2555SubString(后缀自动机,Link-Cut Tree)

BZOJ 2555 SubString 后缀自动机+LCT

字符串(LCT,后缀自动机):BZOJ 2555 SubString

bzoj 2555 SubString——后缀自动机+LCT