zoukankan      html  css  js  c++  java
  • 字符串(LCT,后缀自动机):BZOJ 2555 SubString

    2555: SubString

    Time Limit: 30 Sec  Memory Limit: 512 MB
    Submit: 1620  Solved: 471

    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

      注意这个mask不会在函数内改变……

      1 #include <iostream>
      2 #include <cstring>
      3 #include <cstdio>
      4 using namespace std;
      5 const int maxn=1200010;
      6 int cnt,last;
      7 int FA[maxn],CH[maxn][27],len[maxn],rt[maxn];
      8 int fa[maxn],ch[maxn][2],add[maxn],key[maxn],flip[maxn];
      9 
     10 void Add(int x,int d){
     11     if(!x)return;
     12     key[x]+=d;
     13     add[x]+=d;
     14 }
     15 
     16 void Flip(int x){
     17     swap(ch[x][0],ch[x][1]);
     18     flip[x]^=1;
     19 }
     20 
     21 void Push_down(int x){
     22     if(add[x]){
     23         Add(ch[x][0],add[x]);
     24         Add(ch[x][1],add[x]);
     25         add[x]=0;
     26     }
     27     if(flip[x]){
     28         Flip(ch[x][0]);
     29         Flip(ch[x][1]);
     30         flip[x]=0;
     31     }
     32 }
     33 
     34 void Rotate(int x){
     35     int y=fa[x],g=fa[y],c=ch[y][1]==x;
     36     ch[y][c]=ch[x][c^1];fa[ch[y][c]]=y;
     37     ch[x][c^1]=y;fa[y]=x;fa[x]=g;
     38     if(rt[y])rt[y]=false,rt[x]=true;
     39     else ch[g][ch[g][1]==y]=x;
     40 }
     41 
     42 void P(int x){
     43     if(!rt[x])P(fa[x]);
     44     Push_down(x);
     45 }
     46 
     47 void Splay(int x){
     48     P(x);
     49     for(int y=fa[x];!rt[x];Rotate(x),y=fa[x])
     50         if(!rt[y])Rotate((ch[fa[y]][1]==y)==(ch[y][1]==x)?y:x);        
     51 }
     52 
     53 void Access(int x){
     54     int y=0;
     55     while(x){
     56         Splay(x);
     57         rt[ch[x][1]]=true;
     58         rt[ch[x][1]=y]=false;
     59         x=fa[y=x];
     60     }
     61 }
     62 
     63 void Lca(int &x,int &y){
     64     Access(y);y=0;
     65     while(true){
     66         Splay(x);
     67         if(!fa[x])break;
     68         rt[ch[x][1]]=true;
     69         rt[ch[x][1]=y]=false;
     70         x=fa[y=x];
     71     }
     72 }
     73 
     74 void Make_rt(int x){
     75     Access(x);
     76     Splay(x);
     77     Flip(x);
     78 }
     79 
     80 void Change(int x,int y,int d){
     81     Lca(x,y);key[x]+=d;
     82     Add(y,d);Add(ch[x][1],d);
     83 }
     84 
     85 void Link(int x,int y){
     86     Make_rt(x);
     87     Splay(x);
     88     fa[x]=y;
     89     Change(1,y,key[x]);
     90 }
     91 
     92 void Cut(int x,int y){
     93     Make_rt(x);
     94     Splay(y);
     95     fa[ch[y][0]]=fa[y];
     96     fa[y]=0;rt[ch[y][0]]=true;
     97     ch[y][0]=0;
     98     Change(1,y,-key[x]);
     99 }
    100 
    101 
    102 
    103 struct SAM{
    104     void Init(){
    105         memset(FA,0,sizeof(FA));
    106         memset(CH,0,sizeof(CH));
    107         memset(rt,-1,sizeof(rt));
    108         last=cnt=1;
    109     }
    110     
    111     void Insert(int c){
    112         int p=last,np=last=++cnt;len[np]=len[p]+1;key[np]=1;
    113         while(p&&!CH[p][c])CH[p][c]=np,p=FA[p];
    114         if(!p)FA[np]=1;
    115         else{
    116             int q=CH[p][c];
    117             if(len[p]+1==len[q])
    118                 FA[np]=q;
    119             else{
    120                 int nq=++cnt;len[nq]=len[p]+1;
    121                 memcpy(CH[nq],CH[q],sizeof(CH[q]));
    122                 FA[nq]=FA[q];FA[q]=FA[np]=nq;
    123                 
    124                 Link(nq,FA[nq]);Cut(q,FA[nq]);Link(q,nq);
    125                 
    126                 while(CH[p][c]==q)
    127                     CH[p][c]=nq,p=FA[p];
    128             }    
    129         }
    130         Link(np,FA[np]);
    131     }
    132     void Extend(char *s){
    133         int l=strlen(s);
    134         for(int i=0;i<l;i++)
    135             Insert(s[i]-'A');
    136     }
    137     
    138     int Solve(char *s){
    139         int l=strlen(s),p=1;
    140         for(int i=0,c;i<l;i++){
    141             c=s[i]-'A';
    142             if(!CH[p][c])return 0;
    143             else p=CH[p][c];
    144         }
    145         Splay(p);
    146         return key[p];
    147     }
    148 }sam;
    149 
    150 char s[maxn];
    151 char op[10];
    152 int ans,mask,Q;
    153 
    154 void Decode(char *str,int t){
    155     int l=strlen(str);
    156     for(int i=0;i<l;i++){
    157         t=(t*131+i)%l;
    158         swap(str[i],str[t]);
    159     }
    160 }
    161 
    162 int main(){
    163     sam.Init();
    164     scanf("%d",&Q);
    165     scanf("%s",s);
    166     sam.Extend(s);
    167     while(Q--){
    168         scanf("%s",op);
    169         scanf("%s",s);Decode(s,mask);
    170         if(op[0]=='A')
    171             sam.Extend(s);
    172         else{
    173             ans=sam.Solve(s);
    174             printf("%d
    ",ans);
    175             mask^=ans;
    176         }
    177     }
    178     return 0;
    179 }
    尽最大的努力,做最好的自己!
  • 相关阅读:
    springmvc入门详解
    getClass 与getSimpleName
    mybati的存储过程
    mybatis与spring的整合
    mybatis分页插件以及懒加载
    mybatis知识总结
    【Java面试题】30 子线程循环10次,接着主线程循环100,接着又回到子线程循环10次,接着再回到主线程又循环100,如此循环50次,请写出程序。
    【Java面试题】29 设计4个线程,其中两个线程每次对j增加1,另外两个线程对j每次减少1。写出程序。
    【Java面试题】28 简述synchronized和java.util.concurrent.locks.Lock的异同 ?
    【Java面试题】27 多线程笔试面试概念问答
  • 原文地址:https://www.cnblogs.com/TenderRun/p/5591534.html
Copyright © 2011-2022 走看看