zoukankan      html  css  js  c++  java
  • BZOJ 2555 Substrings 题解

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

    构建SAM,再用LCT维护Parent Tree。每次新加一个结点,对它的祖先的Right集合大小都加了1,(Right集合的定义见CLJ的ppt。这里不需要真的存储Right集合,存集合大小即可)

    细节比较多,很容易写错。。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 const int MAXN=600000+5;
      5 const int MAXQ=3000000+5;
      6 const int SIGMA_SIZE=26;
      7 inline int idx(char c)
      8 {    return c-'A';    }
      9 namespace LCT{
     10     struct Node{
     11         Node* p,*ch[2];
     12         int cnt,add;
     13         Node() {cnt=add=0;p=ch[0]=ch[1]=0;}
     14         inline bool d() const
     15         {    return p->ch[1]==this;    }
     16         inline void setc(Node* t,bool d)
     17         {
     18             ch[d]=t;
     19             t->p=this;
     20         }
     21         inline void addIt(int ad)
     22         {
     23             add+=ad;
     24             cnt+=ad;
     25         }
     26         inline void pushdown();
     27         inline bool isRoot() const;
     28     }*null;
     29     inline void Node::pushdown()
     30     {
     31         if(add)
     32         {
     33             if(ch[0]!=null) ch[0]->addIt(add);
     34             if(ch[1]!=null) ch[1]->addIt(add);
     35             add=0;
     36         }
     37     }
     38     inline bool Node::isRoot()const
     39     {    return p==null || (p->ch[0]!=this && p->ch[1]!=this);    }
     40     Node mem[MAXN<<1],*cur;
     41     inline Node* newNode()
     42     {
     43         Node* t=cur++;
     44         t->ch[0]=t->ch[1]=t->p=null;
     45         return t;
     46     }
     47     inline void rotate(Node* t)
     48     {
     49         Node* p=t->p;
     50         p->pushdown();t->pushdown();
     51         bool d=t->d();
     52         if(!p->isRoot()) p->p->setc(t,p->d());
     53         else t->p=p->p;
     54         p->setc(t->ch[d^1],d);
     55         t->setc(p,d^1);
     56     }
     57     void splay(Node* t)
     58     {
     59         t->pushdown();
     60         while(!t->isRoot())
     61         {
     62             if(t->p->isRoot()) rotate(t);
     63             else t->d()==t->p->d()?(rotate(t->p),rotate(t)):(rotate(t),rotate(t));
     64         }
     65     }
     66     inline void access(Node* u)
     67     {
     68         for(Node* v=null;u!=null;v=u,u=u->p)
     69         {
     70             splay(u);
     71             u->setc(v,1);
     72         }
     73     }
     74     void cut(Node* u) //cut u and its parent
     75     {
     76         access(u);
     77         splay(u);
     78         if(u->ch[0]==null) return;
     79         Node* f=u->ch[0];
     80         while(f->ch[1]!=null) f=f->ch[1];
     81         splay(f);
     82         f->setc(null,1);
     83         f->ch[1]->p=null;
     84     }
     85     void addToRoot(Node* u)
     86     {
     87         access(u);
     88         splay(u);
     89         u->ch[0]->addIt(1);
     90     }
     91     void init()
     92     {
     93         cur=mem;
     94         null=cur++;
     95     }
     96 }
     97 
     98 struct State{
     99     State* go[SIGMA_SIZE],*suf;
    100     LCT::Node *node;
    101     int val;
    102     State():val(0),suf(0) {memset(go,0,sizeof go);}
    103 }*root,*last;
    104 State stateMem[MAXN<<1],*cur;
    105 State* newState()
    106 {
    107     cur->node=LCT::newNode();
    108     return cur++;
    109 }
    110 void init()
    111 {
    112     LCT::init();
    113     cur=stateMem;
    114     root=last=newState();
    115 }
    116 void extend(int w)
    117 {
    118     State* p=last,*np=newState();
    119     np->val=p->val+1;
    120     LCT::Node* nd=np->node;
    121     nd->cnt=1;
    122     while(p && !p->go[w]) p->go[w]=np,p=p->suf;
    123     if(!p) np->suf=root,nd->p=root->node;
    124     else
    125     {
    126         State* q=p->go[w];
    127         if(q->val==p->val+1) np->suf=q,nd->p=q->node;
    128         else
    129         {
    130             State* nq=newState();
    131             nq->val=p->val+1;
    132             memcpy(nq->go,q->go,sizeof(q->go));
    133             LCT::cut(q->node);
    134             nq->suf=q->suf;
    135             nq->node->cnt=q->node->cnt;
    136             nq->node->p=q->suf->node;
    137             q->suf=np->suf=nq;
    138             q->node->p=nd->p=nq->node;
    139             while(p && p->go[w]==q) p->go[w]=nq,p=p->suf;
    140         }
    141     }
    142     LCT::addToRoot(nd);
    143     last=np;
    144 }
    145 void decodeWithMask(char *s,int len,int mask)
    146 {
    147     for(int i=0;i<len;++i)
    148     {
    149         mask=(mask*131+i)%len;
    150         std::swap(s[i],s[mask]);
    151     }
    152 }
    153 int query(char* s,int len)
    154 {
    155 //    printf("%s
    ",s);
    156     State* t=root;
    157     for(int i=0;i<len;++i)
    158     {
    159         int w=idx(s[i]);
    160         if(!t->go[w]) return 0;
    161         t=t->go[w];
    162     }
    163     LCT::splay(t->node);
    164     return t->node->cnt;
    165 }
    166 void insert(char* s,int len)
    167 {
    168 //    printf("%s
    ",s);
    169     for(int i=0;i<len;++i)
    170         extend(idx(s[i]));
    171 }
    172 char cmd[10],s[MAXQ];
    173 int main()
    174 {
    175     init();
    176     int Q;
    177     scanf("%d",&Q);
    178     scanf("%s",s);
    179     insert(s,strlen(s));
    180     int mask=0;
    181     while(Q--)
    182     {
    183         scanf("%s%s",cmd,s);
    184         decodeWithMask(s,strlen(s),mask);
    185         if(cmd[0]=='Q')
    186         {
    187             int t=query(s,strlen(s));
    188             mask^=t;
    189             printf("%d
    ",t);
    190         }
    191         else insert(s,strlen(s));
    192     }
    193     return 0;
    194 }
    View Code
  • 相关阅读:
    【剑指offer】不使用新变量,交换两个变量的值,C++实现
    【剑指offer】不用加减乘除做加法,C++实现
    【剑指offer】求1+2+…+n,C++实现
    【剑指offer】左旋转字符串,C+实现
    给记事本添加接口,并通过菜单来执行自定义的功能
    修改PE文件的入口函数OEP
    360搜集隐私程序员级分析,供方舟子及大众参考
    Android窃取用户信息新思路
    如何整治那些敢偷用你Wi-Fi的人
    保护WIFI无线网络的安全
  • 原文地址:https://www.cnblogs.com/lowsfish/p/4415403.html
Copyright © 2011-2022 走看看