Never-ending tune the code

Who loves who tune to tune, I am his mother did not transfer such a sucker code. 

code: 

#include <cstdio> 
#include <algorithm> 
#include <cstring> 
#include <string>  
#include <vector> 
#include <map>        
#define N 100007 
#define inf 0x3f3f3f3f   
#define ull unsigned long long  

// 代码已写完,人已阵亡.  
    
using namespace std; 

int K1,K2;  
ull ans,W;  
char S[N];     

namespace IO {   

    void setIO(string s) 
    {
        string in=s+".in"; 
        string out=s+".out"; 
        freopen(in.c_str(),"r",stdin); 
        // freopen(out.c_str(),"w",stdout);  
    } 

};  

struct SAM {        

    #define M N<<1   

    int tot,last;     
    struct Edge {   
        int to,w;  
        Edge(int to=0,int w=0):to(to),w(w){}    
    };   
    vector<Edge>G[M];  
    int pre[M],ch[M][26],mx[M],str_sam[M],sam_str[M],depth[M];               

    void Initialize() { tot=last=1; }     

    void extend(int c) 
    {         
        int np=++tot,p=last;   
        mx[np]=mx[p]+1,last=np; 
        for(;p&&!ch[p][c];p=pre[p]) ch[p][c]=np;   
        if(!p) pre[np]=1; 
        else 
        {
            int q=ch[p][c];  
            if(mx[q]==mx[p]+1) pre[np]=q;  
            else 
            {
                int nq=++tot;     
                mx[nq]=mx[p]+1;    
                memcpy(ch[nq],ch[q],sizeof(ch[q]));    
                pre[nq]=pre[q],pre[np]=pre[q]=nq;    
                for(;p&&ch[p][c]==q;p=pre[p])  ch[p][c]=nq;  
            }
        }      
    } 
    

    void Build_LCP() 
    {       
        int n=strlen(S+1),i,j,p=1; 
        for(i=1;i<=n;++i)  
        { 
            p=ch[p][S[n-i+1]-'a'];   
            sam_str[p]=n-i+1; 
            str_sam[n-i+1]=p;                     
        }
        for(i=2;i<=tot;++i) 
        {
            if(mx[i]>K1) depth[i]=0;           
            else depth[i]=mx[i];   
        }
        for(i=2;i<=tot;++i)  G[pre[i]].push_back(Edge(i,depth[i]-depth[pre[i]]));         
    }   
    
    void Build_LCS()
    {
        int n=strlen(S+1),i,j,p=1;   
        for(i=1;i<=n;++i) 
        {
            p=ch[p][S[i]-'a'];   
            sam_str[p]=i;  
            str_sam[i]=p;   
        }    
        for(i=2;i<=tot;++i)  
        {
            if(mx[i]>K2) depth[i]=0; 
            else  depth[i]=mx[i]; 
        }
        for(i=2;i<=tot;++i)  G[pre[i]].push_back(Edge(i,depth[i]-depth[pre[i]]));   
    }     

    #undef M  

}lcp,lcs;  

namespace vir {      

    vector<int>G[N<<1];  

    int t,sta,tot;  
    int is1[N],is2[N];  
    int dfn[N],S[N],dep[N],size[N],son[N],top[N],f[N],val[N],col[N],re[N];  
    ull size1[N],size2[N],sizew[N];      
    ull sum1[N],sum2[N],sumw[N];          

    bool cmp(int a,int b) 
    {
        return dfn[a]<dfn[b];   
    }

    void get_dfn(int x,int fa) 
    { 
        dfn[x]=++t;           
        size[x]=1; 
        f[x]=fa;   
        for(int i=0;i<lcp.G[x].size();++i) 
        {
            int y=lcp.G[x][i].to;   
            if(y==fa) continue;   
            get_dfn(y,x);     
            dep[y]=dep[x]+1;    
            size[x]+=size[y];  
            if(size[y]>size[son[x]]) son[x]=y; 
        }        
    }   

    void dfs2(int u,int tp) 
    {
        top[u]=tp; 
        if(son[u]) dfs2(son[u],tp); 
        for(int i=0;i<lcp.G[u].size();++i) 
        {
            int v=lcp.G[u][i].to;    
            if(v==son[u]||v==f[u]) continue;     
            dfs2(v,v);    
        }
    }  

    int LCA(int x,int y) 
    { 
        while(top[x]!=top[y]) 
        {
            dep[top[x]]>dep[top[y]]?x=f[top[x]]:y=f[top[y]];  
        } 
        return dep[x]<dep[y]?x:y;  
    }  

    void _new(int x,int v,int c) 
    { 
        ++tot; 
        re[tot]=x; 
        val[x]=v; 
        col[x]=c;       
        if(c==1) is1[x]=1; 
        else is2[x]=1;  
    }    

    void addvir(int x,int y) 
    {   
        G[x].push_back(y); 
    } 

    void Initialize() 
    {
        t=0;   
        get_dfn(1,0);   
        dfs2(1,1);            
    }       

    void Insert(int x) 
    { 
        if(sta<=1) 
        {
            S[++sta]=x;      
            return;  
        }
        int lca=LCA(S[sta],x);       
        if(lca==S[sta]) S[++sta]=x;  
        else 
        {
            while(sta>1&&dep[S[sta-1]]>=dep[lca]) addvir(S[sta-1],S[sta]),--sta;    
            if(S[sta]==lca)  S[++sta]=x;                           
            else 
            {
                addvir(lca,S[sta]);   
                S[sta]=lca;  
                S[++sta]=x;   
            }   
        }
    }  

    void Build() 
    {    
        sta=0;  
        sort(re+1,re+1+tot,cmp); 
        if(re[1]!=1) S[++sta]=1;           
        for(int i=1;i<=tot;++i) Insert(re[i]);   
        while(sta>1)  addvir(S[sta-1],S[sta]),--sta;                           
    }    

    void DP(int x) 
    {    
        for(int i=0;i<G[x].size();++i) 
        {
            int y=G[x][i];  
            DP(y);            
            size1[x]+=size1[y]; 
            size2[x]+=size2[y];   
            sum1[x]+=sum1[y];   
            sum2[x]+=sum2[y];               
        } 
        ull tmp=0;   
        ull cntw=0; 
        ull cur=0;   
        for(int i=0;i<G[x].size();++i) 
        {   
            int y=G[x][i];     
            tmp+=(sum1[x]-sum1[y])*size2[y];        
            tmp+=(sum2[x]-sum2[y])*size1[y];              
            cntw+=(size1[x]-size1[y])*size2[y];  
        }    
        cur+=(tmp)*lcp.depth[x];           
        cur-=(cntw)*W*lcp.depth[x];                    
        cur+=is1[x]*size2[x]*val[x]*lcp.depth[x]+is2[x]*size1[x]*val[x]*lcp.depth[x];    
        cur-=(is1[x]*size2[x]*W+is2[x]*size1[x]*W);     
        ans+=cur/2;    
        size1[x]+=is1[x];  
        size2[x]+=is2[x];   
        sum1[x]+=is1[x]*val[x];  
        sum2[x]+=is2[x]*val[x];     
    }

    void solve() 
    {
        Build();   
        DP(1);              
        for(int i=1;i<=tot;++i) 
        {
            re[i]=val[i]=sum1[i]=sum2[i]=size1[i]=size2[i]=is1[i]=is2[i]=0;       
            G[i].clear();  
            re[i]=0;  
        }  
        tot=0;   
        sta=0;   
    }
};  // 虚树  

int tot,edges=1; 
int totsize,rt1,rt2,mx,ed,lsc,rsc;  
int hd[N<<3],vis[N<<3],size[N<<3];  

struct Edge {
    int to,w,nex;   
}e[N<<3];    
 
struct Node {   
    int u,dis,val;        
    Node(int u=0,int dis=0,int val=0):u(u),dis(dis),val(val){}           
}L[N<<2],R[N<<2]; 

void add_div(int x,int y,int z) 
{
    e[++edges].nex=hd[x],hd[x]=edges,e[edges].to=y,e[edges].w=z;   
}    

void Build_Tree(int x,int fa) 
{ 
    int ff=0;               
    for(int i=0;i<lcs.G[x].size();++i) 
    {
        int y=lcs.G[x][i].to;   
        if(y==fa)  continue;    
        if(!ff) 
        {
            ff=x;    
            add_div(ff,y,lcs.G[x][i].w);  
            add_div(y,ff,lcs.G[x][i].w);    
        }
        else 
        {
            ++tot;     
            add_div(ff,tot,0);  
            add_div(tot,ff,0);   
            add_div(tot,y,lcs.G[x][i].w);   
            add_div(y,tot,lcs.G[x][i].w);   
            ff=tot;          
        }
        Build_Tree(y,x);   
    }
}

void find_edge(int x,int fa)
{    
    size[x]=1;  
    for(int i=hd[x];i;i=e[i].nex) 
    {
        int y=e[i].to;   
        if(y==fa||vis[i])  continue;    
        find_edge(y,x);  
        size[x]+=size[y];
        int now=max(size[y],totsize-size[y]);    
        if(now<mx) 
        {
            mx=now;  
            ed=i;   
            rt1=x,rt2=y;    
        }
    }
} 


void get_node(int x,int fa,int dep,int ty) 
{       
    if(ty==0) 
    {             
        if(lcs.sam_str[x])  L[++lsc]=Node(lcs.sam_str[x],lcs.mx[x]-dep,dep);   
    } 
    else 
    {    
        if(lcs.sam_str[x])  R[++rsc]=Node(lcs.sam_str[x],lcs.mx[x]-dep,dep);  
    }
    for(int i=0;i<lcs.G[x].size();++i) 
    {
        int y=lcs.G[x][i].to;     
        if(vis[i]||y==fa)  continue;    
        get_node(y,x,dep+lcs.G[x][i].w,ty);   
    }
}   

void Divide_And_conquer(int x) 
{       
    if(totsize==1) return;  
    mx=inf;   
    rt1=rt2=ed=0;      
    find_edge(x,0);     
    vis[ed]=vis[ed^1]=1;      
    lsc=rsc=0;                                        
    get_node(rt1,0,0,1);   
    get_node(rt2,0,0,2);                                       
    for(int i=1;i<=lsc;++i) vir::_new(lcp.str_sam[L[i].u],L[i].dis,1);    
    for(int i=1;i<=rsc;++i) vir::_new(lcp.str_sam[R[i].u],R[i].dis,2);         
    W=e[ed].w;  
    vir::solve();         
    int tmprt1=rt1,tmprt2=rt2;            
    int sizert1=size[rt1],sizert2=totsize-size[rt1];    
    totsize=sizert1;        
    Divide_And_conquer(tmprt1);      
    totsize=sizert2;   
    Divide_And_conquer(tmprt2);   
} 

int main() 
{ 
    IO::setIO("input");  
    int i,j,n;   
    scanf("%s%d%d",S+1,&K1,&K2);          
    n=strlen(S+1);      
    lcp.Initialize();   
    lcs.Initialize();   
    for(i=1;i<=n;++i)  
    {
        lcs.extend(S[i]-'a');   
        lcp.extend(S[n-i+1]-'a');   
    }
    lcs.Build_LCS();   
    lcp.Build_LCP();  
    tot=lcs.tot;       
    Build_Tree(1,0);   
    vir::Initialize();   
    totsize=n;  
    printf("%llu\n",ans);   
    return 0; 
}

  

Guess you like

Origin www.cnblogs.com/guangheli/p/12107723.html