【bzoj 2555】SubString(SAM+LCT)

傳送門biu~
查詢一個串出現了幾次,即詢問SAM上表示這個串的的Right數組有幾個。當我們向SAM上添加一個節點時,這個節點在parent樹上到根的路徑上的所有節點Right數組數量都會+1。可以用LCT維護。
本來說快省選了在省選完掛之前寫一道聽起來很厲害的SAM+LCT,退役了也沒什麼遺憾了。沒想到其實就是在維護SAM的時候順便維護一個LCT,而且還1A了。生活失去了色彩,退役了退役了。。。

#include<bits/stdc++.h>
using namespace std;
struct splay{
    splay *fa,*ch[2];
    int mark,val;
    splay();
    inline void pushdown();
    inline void add(int);
    inline int dir(){
        if(fa->ch[0]==this) return 0;
        if(fa->ch[1]==this) return 1;
        return -1;
    }
}*null=new splay;
splay :: splay(){
    fa=ch[0]=ch[1]=null;
    mark=val=0;
}
inline void splay :: add(int v){
    if(this==null)  return;
    val+=v; mark+=v;
}
inline void splay :: pushdown(){
    if(!mark)   return;
    ch[0]->add(mark);
    ch[1]->add(mark);
    mark=0;
}
void To_pushdown(splay *o){
    if(~o->dir())  To_pushdown(o->fa);
    o->pushdown();
}
inline void Rotate(splay *o,int d){
    splay *k=o->ch[d^1];
    o->ch[d^1]=k->ch[d];    k->ch[d]->fa=o;
    k->ch[d]=o;
    if(~o->dir())  o->fa->ch[o->dir()]=k;
    k->fa=o->fa;    o->fa=k;
}
inline void Splay(splay *o){
    To_pushdown(o);
    while(~o->dir()){
        if(o->dir()==o->fa->dir())  Rotate(o->fa->fa,o->dir()^1);
        Rotate(o->fa,o->dir()^1);
    }
}
inline void Access(splay *o){
    splay *p=null;
    while(o!=null){
        Splay(o);
        o->ch[1]=p;
        p=o;
        o=o->fa;
    }
}
inline void Cut(splay *o){
    Access(o);  Splay(o);
    o->ch[0]=o->ch[0]->fa=null;
}
inline void Link(splay *x,splay *y){
    Cut(x); x->fa=y;
}
struct Node{
    Node *fa,*ch[26];
    int val;
    splay *tree;
    Node(int _=0){
        fa=0x0; val=_;
        memset(ch,0x0,sizeof ch);
        tree=new splay;
    }
}*root=new Node,*last=root;
inline void Insert(int x){
    Node *p=last,*np=new Node(p->val+1);last=np;
    while(p && !p->ch[x])   p->ch[x]=np,p=p->fa;
    if(!p)  np->fa=root,Link(np->tree,root->tree);
    else{
        Node *q=p->ch[x];
        if(q->val==p->val+1)    np->fa=q,Link(np->tree,q->tree);
        else{
            Node *nq=new Node(p->val+1);
            nq->fa=q->fa;   Link(nq->tree,q->fa->tree);
            memcpy(nq->ch,q->ch,sizeof nq->ch);
            q->fa=nq;   Link(q->tree,nq->tree);
            np->fa=nq;  Link(np->tree,nq->tree);
            To_pushdown(q->tree);
            nq->tree->val=q->tree->val;
            while(p && p->ch[x]==q) p->ch[x]=nq,p=p->fa;
        }
    }
    Access(np->tree);
    Splay(np->tree);
    np->tree->add(1);
}
char s[600005];
inline void s_Insert(){
    for(int i=0;s[i];++i)   Insert(s[i]-'A');
}
inline int search(){
    Node *o=root;
    for(int i=0;s[i];++i){
        if(!o->ch[s[i]-'A'])    return 0;
        o=o->ch[s[i]-'A'];
    }
    To_pushdown(o->tree);
    return o->tree->val;
}
inline void Decode(int mask){
    int n=strlen(s);
    for(int i=0;i<n;++i){
        mask=(mask*131+i)%n;
        swap(s[i],s[mask]);
    }
}
int main(){
    int n;
    scanf("%d%s",&n,s);
    s_Insert();
    int mask=0;
    for(int i=1;i<=n;++i){
        char opt[10];
        scanf("%s%s",opt,s);
        Decode(mask);
        if(opt[0]=='A')     s_Insert();
        else{
            int ans=search();
            mask^=ans;
            printf("%d\n",ans);
        }
    }
    return 0;
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章