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\n",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\n",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\n",t); 190 } 191 else insert(s,strlen(s)); 192 } 193 return 0; 194 }