조정할 코드를 끝없는

누가 조정에 조정, 나는 그의 어머니는 빨판 코드를 전송하지 않은 누군지 사랑한다. 

암호: 

#INCLUDE <cstdio> 
#INCLUDE <알고리즘> 
#INCLUDE <CString을> 
사용법 #include <문자열>  
#INCLUDE <벡터> 
사용법 #include <지도>        
#DEFINE N 100007 
#DEFINE INF 0x3f3f3f3f   
#DEFINE ULL 부호 오래 오래  

코드가 기록 된 // 명이 사망했다.  
    
네임 스페이스를 사용하여 표준; 

INT K1, K2;  
ULL 년, W;  
문자 S [N];     

네임 스페이스 IO {   

    무효 setIO (문자열들) 
    {
        = S +에서 문자열 "에."; 
        . "밖으로"= S + 밖으로 문자열; 
        freopen을 (in.c_str (), "R"표준 입력); 
        // freopen을 (out.c_str (), "w", 표준 출력);  
    } 

};  

구조체 SAM {        

    #DEFINE M N << 1   

    , 부담 int로;     
    구조체 에지 {   
        , w을 int로;  
        에지 (= 0 INT, INT w = 0)로 (에), w} {(w)    
    };   
    벡터 <엣지> G [M];  
    INT 사전 [M], CH [M] [26], MX [M] str_sam [M] sam_str [M], 깊이 [M];               

    보이드는 초기화 () {TOT 지난 = = 1; }     

    공간 확장 (INT의 c) 
    {         
        INT의 순이익은 = ++ 어린 아이는, p는 지난 =;   
        MX [NP = MX [P] + 1 = 마지막 NP; 
        대 (p는 && CH [P] [C]! 미리 p = [P]) CH [P] [C] = NP;   
        (! P) 이전 [순이익] = 1 인 경우; 
        그밖에 
        {
            INT Q = CH [P] [C]  
            경우 (MX [Q] == MX [P] +1) 미리 [NP = Q;  
            그밖에 
            {
                NQ = INT ++ 모든;     
                MX [NQ = MX [P] +1;    
                memcpy가 (CH [NQ, CH [Q]를 sizeof (CH [Q]));    
                [Q]를 미리 = NQ] 미리 [NP]를 미리 사전 = [Q] = NQ;    
                대 (p는 && CH [P] [C] == Q; p = [P] 사전) CH [P]을 [C] = NQ;  
            }
        }      
    } 
    

    보이드 Build_LCP () 
    {       
        INT의 strlen N = (S + 1), I, J, p = 1; 
        대해 (ⅰ = 1; 나는 <= N; ++ I)  
        { 
            p = CH [P] [S [N-1 +] - 'A'];   
            sam_str [P] = N-1 +; 
            str_sam [N-I + 1] = P;                     
        }
        대 (ⅰ = 2; I <= TOT; I ++) 
        {
            경우 (MX [I]> K1) 깊이 [I] = 0;           
            다른 깊이 [I] = MX [I];   
        }
        위한은 (i = 2; 나는 <= TOT; I ++) G [중고 [I]와 push_back EDGE ((I, 깊이 [I] -depth [중고 [I])).;         
    }   
    
    보이드 Build_LCS ()
    {
        INT의 strlen N = (S + 1), I, J, p = 1;   
        대해 (ⅰ = 1; 나는 <= N; ++ I) 
        {
            p = CH [P] [S [I] - 'A'];   
            sam_str [I] = 1;  
            str_sam [I] = P;   
        }    
        대 (ⅰ = 2; I <= TOT; I ++)  
        {
            경우 (MX [I]> K2) 깊이 [I] = 0; 
            다른 깊이 [I] = MX [I]; 
        }
        위한은 (i = 2; 나는 <= TOT; I ++) G [중고 [I]와 push_back EDGE ((I, 깊이 [I] -depth [중고 [I])).;   
    }     

    #undef를 M  

} LCP, LCS;  

에 대한 네임 스페이스 {      

    벡터 <INT> G [N << 1];  

    INT t, 역, 모든;  
    INT IS1 [N], IS2 [N];  
    INT의 DFN [N], S [N], DEP [N], 크기 [N], 아들 [N], 상위 [N], F [N], 발 [N], COL [N], 재 [N] ;  
    ULL의 크기 1 [N], SIZE2 [N] sizew [N];      
    ULL SUM1 [N], SUM2 [N] sumw [N];          

    부울 CMP (INT의 B, A INT) 
    {
        DFN 복귀 [A] <DFN [B]   
    }

    보이드 get_dfn (INT의 X, INT FA) 
    { 
        DFN [X] = t ++;           
        크기 [X] = 1; 
        F [X] = 일;   
        대해 INT (I = 0; I는 <lcp.G [X] 크기는 (); I ++) 
        {
            INT의 lcp.G Y = [X] [I] .TO;   
            (Y == FA)가 계속되는 경우;   
            get_dfn (Y, X);     
            DEP [Y] = DEP [X] + 1;    
            크기 [X] + = 크기 [Y];  
            경우 (크기 [Y] "의 크기 [아들 [X]) 아들 [X = Y; 
        }        
    }   

    보이드 DFS2 (INT U, INT TP) 
    {
        가기 [U] = TP; 
        경우 (SON [U]) DFS2 (SON [U] TP); 
        경우 (나는 <lcp.G [U] 크기는 (); INT 난 = 0 ++ I) 
        {
            V = INT lcp.G [U] [I] .TO;    
            경우 (V == 아들 [U] || V == F [U]) 계속;     
            DFS2 (V, V);    
        }
    }  

    INT LCA INT (X, Y의 INT) 
    { 
        반면 (상부 [X]! = 가기 [Y]) 
        {
            DEP [가기 [X]> 출발 [가기 [Y] X = F [가기 [X] : Y = F [가기 [Y];  
        } 
        [X] <출발을 증착 복귀 [Y] X : Y;?  
    }  

    보이드 _new (INT의 X, V INT, INT의 c) 
    { 
        최대 ++; 
        다시 [모든] = X; 
        발 [X] = V; 
        COL [X] = C;       
        경우 (c == 1) IS1 [X] = 1; 
        다른 IS2 [X] = 1;  
    }    

    보이드 addvir (INT의 X, Y INT) 
    {   
        G [X] .push_back (Y); 
    } 

    무효 초기화 () 
    {
        t = 0;   
        get_dfn (1,0);   
        DFS2 (1,1);            
    }       

    삽입 공간 (INT의 X) 
    { 
        만약 STA (<= 1) 
        {
            S는 [++이다] = X;      
            반환;  
        }
        INT LCA LCA = (S [STA, X);       
        경우 (LCA == S [STA]) S [++ STA] = X;  
        그밖에 
        {
            동안 STA (> 1 && DEP [S [STA-1]> = DEP [LCA]) addvir (S [STA-1], S [STA), - STA;    
            경우 (S [STA] == LCA) S [++ STA] = X;                           
            그밖에 
            {
                addvir (LCA, S [STA]);   
                S [STA] = LCA;  
                S는 [++이다] = X;   
            }   
        }
    }  

    무효 빌드 () 
    {    
        그것은 = 0이고;  
        정렬 (재 + 1 + 1 + 재 TOT, CMP); 
        경우 (재 [1] = 1!) S [++ STA] = 1;           
        위한 (INT 난 = 1; I <= TOT; I ++)를 삽입 (재 [I]);   
        동안 STA (> 1) addvir (S [STA-1], S [STA), - STA;                           
    }    

    보이드 DP (INT의 X) 
    {    
        대해 INT (I = 0; I <G [X] 크기는 (); I ++) 
        {
            INT Y = G [X] [I];  
            DP (Y);            
            크기 1 [X] + = 크기 1 [Y]; 
            SIZE2 [X] + = SIZE2 [Y];   
            SUM1 [X] + = SUM1 [및];   
            SUM2 [X] + = SUM2 [Y];               
        } 
        ULL TMP = 0;   
        울 cntw = 0; 
        ULL CUR = 0;   
        대해 INT (I = 0; I <G [X] 크기는 (); I ++) 
        {   
            INT Y = G [X] [I];     
            TMP = + (SUM1 [X] -sum1 [Y]) * SIZE2 [Y];        
            TMP = + (SUM2 [X] -sum2 [Y]) * 크기 1 [Y];              
            cntw + = (크기 1 [X] -size1 [Y]) * SIZE2 [Y];  
        }    
        CUR + = (TMP) * lcp.depth [X];           
        CUR - = (cntw) * W * lcp.depth [X];                    
        CUR IS1 + = [X] * SIZE2 [X] * 브로 [X] * lcp.depth [X] + IS2 [X] * 크기 1 [X] * 브로 [X] * lcp.depth [X];    
        CUR - = (IS1 [X] * SIZE2 [X] * W + IS2 [X] * 크기 1 [X] * W);     
        년 + = 심장 / 2;    
        크기 1 [X] + = IS1 [X];  
        SIZE2 [X] + = IS2 [X];   
        SUM1 [X] + = IS1 [X] * 브로 [X];  
        SUM2 [X] + = IS2 [X] * 브로 [X];     
    }

    ) (해결 무효화 
    {
        짓다();   
        DP (1);              
        위한 (INT 난 = 1; I <= TOT; I ++) 
        {
            다시 [I] = 브로 [I] = SUM1 [I] = SUM2 [I] = 크기 1 [I] = SIZE2 [I] = IS1 [I] = IS2 [I] = 0;       
            G [I]하는 명확한 ();  
            다시 [I] = 0;  
        }  
        TOT = 0;   
        그것은 = 0이고;   
    }
}; // 가상 트리  

모든 에지 값 int = 1; 
INT totsize, RT1, RT2, MX, ED, LSC, RSC;  
INT HD [N << 3] 힘 [N << 3], 크기 [N << 3];  

구조체 에지 {
    에 INT, NEX w;   
} 즉 [N << 3];    
 
구조체 노드 {   
    그리고, DIS, 발;        
    노드 (나와는 0, = 0 DIS는, 넌 VAL = = 0) 및 (U), DIS (DIS), 발 (발)을 {}           
} L [N << 2], R [N << 2]; 

보이드 add_div (INT의 X, Y INT, INT의 z) 
{
    E [++ 에지] .nex HD = [X] HD [X] = 가장자리 E [에지] .TO = Y, E [에지] .W = Z;   
}    

보이드 Build_Tree (INT의 X, INT FA) 
{ 
    INT FF = 0;               
    대해 INT (I = 0; I는 <lcs.G [X] 크기는 (); I ++) 
    {
        INT의 lcs.G Y = [X] [I] .TO;   
        (Y == FA)가 계속되는 경우;    
        만약 (! FF) 
        {
            FF = X;    
            add_div (FF, Y lcs.G [X] [I] .W);  
            add_div (Y, FF, lcs.G [X] [I] .W);    
        }
        그밖에 
        {
            최대 ++;     
            add_div (FF도, 0);  
            add_div (모두, FF, 0);   
            add_div (TOT, Y lcs.G [X] [I] .W);   
            add_div (Y, TOT, lcs.G [X] [I] .W);   
            FF = 최대;          
        }
        Build_Tree (Y, X);   
    }
}

보이드 find_edge (INT의 X, INT FA)
{    
    크기 [X] = 1;  
    대해 INT (I = HD는 [X] 나, 나는 전자 = [I] .nex) 
    {
        INT Y = E [I] .TO;   
        경우 (Y == FA || 힘 [I]) 계속;    
        find_edge (Y, X);  
        크기 [X] + = 크기 [Y];
        이제 최대 = INT (크기 [Y] totsize 크기 [Y]);    
        경우 (현재 <MX) 
        {
            MX는 이제 =;  
            ED = 1;   
            RT1 = X, RT2 = Y;    
        }
    }
} 


(INT FA의 INT (X), INT DEP, INT 타이) 보이드 get_node 
{       
    경우 (TY == 0) 
    {             
        경우 (lcs.sam_str [X]) L [++ LSC = 노드 (lcs.sam_str [X] lcs.mx [X] -dep, DEP);   
    } 
    그밖에 
    {    
        경우 (lcs.sam_str [X]) R [++ RSC = 노드 (lcs.sam_str [X] lcs.mx [X] -dep, DEP);  
    }
    대해 INT (I = 0; I는 <lcs.G [X] 크기는 (); I ++) 
    {
        INT의 lcs.G Y = [X] [I] .TO;     
        경우 (힘 [I] || Y == FA) 계속;    
        get_node (Y, X, DEP + lcs.G [X] [I] .W, TY);   
    }
}   

보이드 Divide_And_conquer (INT의 X) 
{       
    (totsize == 1) 돌아 가면;  
    MX = INF;   
    RT1 = RT2 = ED = 0;      
    find_edge (X, 0);     
    뷰 [ED] 정도 = [ED ^ 1] = 1;      
    LSC = RSC = 0;                                        
    get_node (rt1,0,0,1);   
    get_node (rt2,0,0,2);                                       
    위한 (INT 난 = 1; I <= LSC; I ++) 비르 :: _ 새로운 (lcp.str_sam [L [i]를 .u], L [i]를 .dis, 1);    
    위한 (INT 난 = 1; I <= RSC; I ++) 비르 :: _ 새로운 (lcp.str_sam [R [i]를 .u], R [i]를 .dis, 2);         
    W = E [ED] .W;  
    대한 :: 해결 ();         
    INT tmprt1 = RT1, RT2 = tmprt2;            
    INT sizert1 크기 = [RT1, sizert2 = totsize 크기 [RT1];    
    totsize = sizert1;        
    Divide_And_conquer (tmprt1);      
    totsize = sizert2;   
    Divide_And_conquer (tmprt2);   
} 

() 주요 int로 
{ 
    IO :: setIO ( "입력");  
    INT I, J, N;   
    scanf와 ( "% S % D % D", S + 1, K1, K2);          
    N = strlen 함수 (S + 1);      
    lcp.Initialize ();   
    lcs.Initialize ();   
    대해 (ⅰ = 1; 나는 <= N; ++ I)  
    {
        lcs.extend (S [I] - 'A');   
        lcp.extend (S [I + N-1] - 'A');   
    }
    lcs.Build_LCS ();   
    lcp.Build_LCP ();  
    lcs.tot 모든 =;       
    Build_Tree (1,0);   
    대한 :: 초기화 ();   
    totsize = N;  
    의 printf ( "%의 LLU \ n", ANS);   
    0을 반환; 
}

  

추천

출처www.cnblogs.com/guangheli/p/12107723.html