zoukankan      html  css  js  c++  java
  • 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]='';
    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
    ",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 }
  • 相关阅读:
    WebClient.UploadData 方法 上载文件数据
    webclient提交并接受返回
    webClient上载下载
    斯特林反演与伯恩赛德引理
    Re0: 从 1 开始的省选前生活
    Windows 8将可能带动触摸屏的发展
    后PC时代的那些事
    关于ASP网页在IIS7.5下访问数失效
    Windows 要终结了?微软要推超级系统?
    未来10年的开放式互联网
  • 原文地址:https://www.cnblogs.com/KKKorange/p/8531959.html
Copyright © 2011-2022 走看看