SPOJ 687 REPEATS--接尾辞配列+ RMQ

フェイス質問

  羅バレー

解決

  最初のオファーPPT YYR

 

   

   このPPTの基本的な考え方は明らかにされているが、他のいくつかの詳細があります

  我々は$と$ Lの*(T + 1)$の後の$ Lの* tを特定し、暴力が明らかに前後にジャンプをジャンプすることはできません。$ LCP(のL * T、Lの*(T + 1))$の点まで戻ってジャンプジャンプを検討し、これは接尾辞配列+ RMQ高速なクエリを前処理を使用することができます。次に何それから、複数のサイクルフェスティバルがある場合は、その後、小さなトンが存在しなければならないので、同じ出発点に前方にジャンプします、1サイクル区間まで生産するために前方にジャンプし、前方にジャンプし、ループ部までの生成を検討ときにループ部を作るのだろうか?

  = LENの%のL」セクション$ kを循環部分を越え順序$ LEN = LCP(のL * T、L×(T + 1))$ / L + 1 $ lenのノット$ RESの=のサイクルのケース番号、 $、明らかに少なくとも$ K = Lの前方にジャンプ場合 - $点」kは、サイクルのセクションを生成することができ、すなわち$のLCP(のL * TK、のL * TK + 1)\場合を満たすgeqslant Lの$ 、$ RES ++ $

 コード:

書式#include <cstdioを> 
する#include <iostreamの> 
の#include <アルゴリズム>
 使用して 名前空間はstdを、
const  int型 MAXN = 50004 ;

INT T、N、ANS。
INT SA [MAXN]、RK [MAXN]、モミ[MAXN]、秒[MAXN]、C [MAXN]、特開平[MAXN]。
チャーS [MAXN]。

無効Build_SAを()
{
    INT、M = 26 以下のためにint型 i = 1 ; iは= N <; ++ I)
        FIR [I] = sの[I] - ' ' + 1 以下のためにint型 i = 0 ; I <= M; ++ I)
        C [I] = 0 ;
    以下のためにint型 i = 1 ; iは= N <; ++ I)
        C [i]はモミ] ++ ;
    以下のためにint型 I = 1 ; I <= M; ++ I)
        C [I] + = C [I- 1 ]。
    以下のためにint型 I = N; I; - I)
        SA [FIR [C [I]] - ] = I。
    int型のk = 1 ; K <= N; kは<< = 1 
    {
        int型、T = 0 ;
        int型 - K + I = N 1 ++; iが<= N I)
            秒【 ++ T] = I。
        以下のためにint型 i = 1 ; iが<= N; ++ I)
             であれば(SA [I]> k)は
                秒【 ++ T] = SA [i]は- kは、
        以下のためにint型 i = 0 ; I <= M; ++ I)
            C [I] = 0 ;
        以下のためにint型 i = 1 ; iは= N <; ++ I)
            C [FIR [秒[I]]] ++ ;
        以下のためにint型 I = 1 ; I <= M; ++ I)
            C [I] + = C [I- 1 ]。
        以下のためにint型 I = N; I; - I)
            SA [FIR [秒[I]]] C - ] =秒[I]、秒[I] = 0 ;
        以下のためにint型 i = 1 ; iは= N <; ++ I)
            スワップ(FIR [I]、秒[I])。
        T = 0 
        FIR [SA [ 1 ] ++ = T。
        int型 iは= 2 ; iが<= N ++ I)の
             場合(SEC [SA [I] =秒[SA [1-が!1 ] ||秒[SA [I] + K] =秒! [SA [I- 1 ] + K])
                FIR [SA [I] = ++ T。
            他の
                モミ[SA [i]を] = T;
        もし(T> = N)、
             ブレーク
        M = T。
    }
    以下のためにint型 i = 1 ; iは= N <; ++ I)
        FIR [I] =秒[I] = 0 ;
}

無効Get_heiを()
{
    INT H = 0 以下のためにint型 i = 1 ; iは= N <; ++ I)
        RK [SA [I] = I。
    以下のためにint型 i = 1 ; iは= N <; ++ I)
    {
        INT T = SA [RK [1] - 1 ]。
        一方、(S [T + H] == sは[IはH +])H ++ 
        特開平[RK [I] =のH;
        H = MAX(0、H - 1 )。
    }
}

INTのためのLG [MAXN]、MN [ 20 ] [MAXN]。

無効)(RMQを
{
    以下のためにint型 i = 1 ; iは= N <; ++ I)
        MN [ 0 ] [I] = 開平[I]。
    INT J = 1 ; J <= LG [N]; ++ j)の
         ためのint型 iは= 1 ; I +(1 << J) - 1 <= N; ++ I)
            MN [J] [I] =分(M N [J- 1 ] [i]は、私[J- 1 ] [I +(1 <<(J- 1 ))])。
}

INTクエリ(int型のx、int型のY)
{
    もし(X> Y)スワップ(X、Y)
    戻り分(MN [LG [Y-X] [X + 1 ]、MN [LG [YX] [Y-(1つの << LG [YX])+ 1 ])。
}

int型のmain()
{
    LG [ 0 ] = - 1 以下のためにint型 I = 1 ; I <= 50000 ; ++ I)
        LG [I] = LG [I >> 1 ] + 1 
    scanf関数(" %のD "、&T)。
    しばらく(T-- 
    {
        scanf関数(" %のD "、&N)
        チャー C [ 5 ]。
        以下のためにint型 i = 1 ; iは= N <; ++ I)
        {
            scanf関数(" %sの" 、C)。
            S [i]は = Cを[ 0 ]。
        }
        S [N + 1 ] = 0 ;
        Build_SA();
        Get_hei();
        RMQ();
        ANS = 1 以下のためにint型 I = 1 ; I <= N; ++ I)
             のためにint型、J = 1、J + I <= N; J + = I)
            {
                int型 L =クエリ(RK [J]、RK [J + I])。
                INT RES = L / I + 1、K = I - 1%I。
                もし(JK &&クエリ(RK [JK]、RK [JK + I])> = I)
                    解像度 ++ ; = MAX(年RES);
                J + =リットル/私は* 私を。
            }
        printf(" %d個の\ n " 、ANS)。
    }
    リターン 0 ;
}
コードの表示

 

おすすめ

転載: www.cnblogs.com/Joker-Yza/p/11348702.html
おすすめ