码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj 5408: string 后缀自动机+动态树

时间:2019-11-10 11:55:24      阅读:119      评论:0      收藏:0      [点我收藏+]

标签:void   can   ext   inpu   which   efi   splay   动态   pac   

联赛前练练码力. 

code:

#include <vector> 
#include <cstdio> 
#include <cstring>    
#include <algorithm>   
#define N 200006      
#define ll long long    
#define lson t[x].ch[0] 
#define rson t[x].ch[1] 
#define setIO(s) freopen(s".in","r",stdin)     
using namespace std;        
struct data
{
    int tim,id;               
    data(int tim=0,int id=0):tim(tim),id(id){}    
};        
struct node 
{    
    int ch[2],f,val[21],tag[21];     
}t[N<<1];        
ll sub; 
int lastans;            
char str[N]; 
int last,tot,n; 
vector<data>G[21];       
int ch[N<<1][11],pre[N<<1],len[N<<1],sta[N<<1];    
inline int get(int x) 
{ 
    return t[t[x].f].ch[1]==x; 
}     
inline int isrt(int x) 
{ 
    return !(t[t[x].f].ch[0]==x||t[t[x].f].ch[1]==x); 
}      
inline void mark(int x,int p,ll v) 
{     
    t[x].val[p]+=v,t[x].tag[p]+=v;           
}        
void pushdown(int x) 
{
    if(!x) return;         
    for(int i=1;i<=n;++i) 
    {
        if(t[x].tag[i])    
        {
            if(lson)   mark(lson,i,t[x].tag[i]);   
            if(rson)   mark(rson,i,t[x].tag[i]);    
            t[x].tag[i]=0;     
        }
    }
}    
void rotate(int x) 
{
    int old=t[x].f,fold=t[old].f,which=get(x);  
    if(!isrt(old))    t[fold].ch[t[fold].ch[1]==old]=x;     
    t[old].ch[which]=t[x].ch[which^1],t[t[old].ch[which]].f=old;  
    t[x].ch[which^1]=old,t[old].f=x,t[x].f=fold; 
}
void splay(int x) 
{
    int u=x,fa,v=0; 
    for(sta[++v]=u;!isrt(u);u=t[u].f)    sta[++v]=t[u].f;   
    for(;v;--v)    pushdown(sta[v]);     
    for(u=t[u].f;(fa=t[x].f)!=u;rotate(x))    
        if(t[fa].f!=u)     rotate(get(fa)==get(x)?fa:x);        
}
void Access(int x) 
{    
    for(int y=0;x;y=x,x=t[x].f) 
    {
        splay(x);          
        rson=y;      
    }
}   
// y 无父亲    
void link(int x,int y) 
{                
    t[y].f=x;     
}
// x 是 y 的父亲   
void cut(int x,int y) 
{
    Access(y),splay(y);                
    t[t[y].ch[0]].f=0;
    t[y].ch[0]=0;      
}
void extend(int id,int c) 
{
    if(ch[last][c]) 
    {
        int p=last;     
        int q=ch[p][c]; 
        if(len[q]==len[p]+1)   last=q;    
        else 
        {   
            int nq=++tot;             
            len[nq]=len[p]+1;   
            memcpy(ch[nq],ch[q],sizeof(ch[q]));       
            cut(pre[q],q);    
            for(int j=1;j<=n;++j)  t[nq].val[j]=t[q].val[j];                                             
            link(pre[q],nq);        
            link(nq,q);       
            pre[nq]=pre[q],pre[q]=nq;                       
            for(;p&&ch[p][c]==q;p=pre[p])    ch[p][c]=nq;       
            last=nq;       
        }
    } 
    else 
    { 
        int np=++tot,p=last;   
        len[np]=len[p]+1,last=np;     
        for(;p&&!ch[p][c];p=pre[p])    ch[p][c]=np;  
        if(!p)   pre[np]=1,link(1,np);        
        else 
        {
            int q=ch[p][c]; 
            if(len[q]==len[p]+1)   pre[np]=q,link(q,np);    
            else 
            { 
                int nq=++tot;  
                len[nq]=len[p]+1;  
                memcpy(ch[nq],ch[q],sizeof(ch[q]));   
                cut(pre[q],q);    
                for(int j=1;j<=n;++j)  t[nq].val[j]=t[q].val[j];
                link(pre[q],nq);   
                link(nq,q);        
                link(nq,np);     
                pre[nq]=pre[q],pre[q]=pre[np]=nq;    
                for(;p&&ch[p][c]==q;p=pre[p])    ch[p][c]=nq;               
            }
        }
        sub+=len[np]-len[pre[np]];      
    }               
    Access(last),splay(last),mark(last,id,1ll);    
}
int main() 
{ 
    // setIO("input"); 
    int i,j,ty,m;      
    scanf("%d%d",&n,&ty);         
    for(tot=i=1;i<=n;++i) 
    {
        scanf("%s",str+1);     
        int len=strlen(str+1);     
        for(last=j=1;j<=len;++j)   extend(i,str[j]-‘0‘);            
        G[i].push_back(data(0,last));          
    }      
    scanf("%d",&m); 
    for(i=1;i<=m;++i) 
    {    
        int op,x,y,z; 
        scanf("%d",&op);  
        if(op==1)
        {     
            scanf("%d%d",&x,&y);      
            y=(y^(lastans*1ll*ty))%10;                   
            last=G[x][G[x].size()-1].id;      
            extend(x,y);
            G[x].push_back(data(i,last));               
        }
        if(op==2) 
        {     
            scanf("%d%d%d",&x,&y,&z);       
            int l=0,r=G[x].size()-1,mid=0,pp=0;         
            while(l<=r) 
            {           
                mid=(l+r)>>1;    
                if(G[x][mid].tim<=y)    pp=G[x][mid].id,l=mid+1;    
                else r=mid-1;    
            }       
            Access(pp),splay(pp);                  
            printf("%d\n",lastans=t[pp].val[z]);             
        }
        if(op==3) 
        {
            printf("%lld\n",sub); 
        }
        if(op==4) 
        {
            scanf("%s",str+1); 
            int len=strlen(str+1),pp=1,flag=0; 
            for(j=1;j<=len;++j)  
            {
                if(ch[pp][str[j]-‘0‘])   pp=ch[pp][str[j]-‘0‘];  
                else { flag=1;break; }
            }
            // 能匹配      
            if(!flag)  
            {          
                Access(pp);    
                int best=0;  
                for(j=1;j<=n;++j)    best=max(best,t[pp].val[j]);     
                lastans=best;         
            } 
            else lastans=0;
            printf("%d\n",lastans);        
        }
    }
    return 0; 
}        

  

bzoj 5408: string 后缀自动机+动态树

标签:void   can   ext   inpu   which   efi   splay   动态   pac   

原文地址:https://www.cnblogs.com/guangheli/p/11829165.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!