luogu列口胡コレクション

P3065 [USACO12DEC】まず!初!

各文字列の各文字のためのトライの確立は、競合があるかどうかを判断するためにトポロジカルソートして、彼の兄弟の性格を考えるのは簡単未満でなければなりません

 

P4070 [SDOI2016]呪文を生成します

S各プレフィックスは、多くの異なる性質の部分文字列を検索します 

新しい文字列を追加した後、それぞれ異なる明らかな増加のSAMはmaxlenをノードの本質である、[NP] - minlenに[NP] + 1 = LEN [NP] - LEN [FA [NP]

#include <ビット/ STDC ++ H>
 使用して 名前空間STDを、
#defineは長い長いLL
 のconst  int型 MAXN = 1E5 + 10 INT LEN [MAXN << 1 ]、FA [MAXN << 1 ]。
unordered_map < int型int型 >息子[MAXN << 1 ];
int型のサイズ、最後;
ボイドは、init(){
    サイズ =最後の= 1 ;
}
int型インサート(int型の){
     int型 P =最後に、NP = ++サイズ。最後= NP。
    LEN [NP] = LEN [P] + 1 (; P &&息子[P] .count(S);!P = FA [P])の息子[P] [S] = NP。
    もし(!P)FA [NP] = 1 ;
    {
         INT Q = 息子[P] [S]。
        もし(LEN [P] + 1 == LEN [Q])FA [NP] = Q。
        他の{
             int型 NQ = ++サイズ。LEN [NQ] = LEN [P] + 1 
            息子[NQ] = 息子[Q]。
            FA [NQ] = FA [Q]。FA [Q] = FA [NP] = NQ。
            (;息子[P] .count(S)&&息子[P]、[S] == Q && P; P = FA [P])息子[P]、[S] = NQ。
        }
    }
  //   coutの<< LEN [最後] << "" << LEN [FA [最後]] <<てendl; 
    返す LEN [最後の] - LEN [FA [最後]];
}
int型N;
INT {main()の
    scanf関数(" %のD "、&N)。
    LLの合計 = 0 ; 初期化();
    int型 iは= 1 ; iが<= N iが++ ){
         int型のX; scanf関数(" %のD "、&x)は、 + = インサート(X)。
         printf(" %LLDの\ nを" 、合計)。
    }
    リターン 0 ;
}
コードの表示

 

P3346 [ZJOI2015]神々は幻想郷に好ま

一般サフィックスオートマトンについて学ぶ(同じSAM上に構築されたすべての文字列を思わ)、そして彼女は、テンプレートのタイトルです

#include <ビット/ STDC ++ H>
 使用して 名前空間STDを、
#defineは長い長いLL
 のconst  int型 MAXN = 1E6 + 10 INT LEN [MAXN << 1 ]、FA [MAXN << 1 ]。
int型の息子[MAXN << 1 ] [ 10 ]。
int型のサイズ。
ボイドは、init(){
    サイズ = 1 
}
int型インサート(int型の、INT 最後){
     int型 P =最後に、NP = ++ サイズ。
    LEN [NP] = LEN [P] + 1 以下のための(!; P &&息子[P] [S]; P = FA [P])の息子[P] [S] = NP。
    もし(!P)FA [NP] = 1 ;
    {
         INT Q = 息子[P] [S]。
        もし(LEN [P] + 1 == LEN [Q])FA [NP] = Q。
        他の{
             int型 NQ = ++サイズ。LEN [NQ] = LEN [P] + 1 
            memcpy(息子[NQ]、息子[Q]、はsizeof (息子[Q]))。
            FA [NQ] = FA [Q]。FA [Q] = FA [NP] = NQ。
            (;息子[P]、[S] &&息子[P]、[S] == Q && P; P = FA [P])息子[P]、[S] = NQ。
        }
    }
    リターンNP。
}
int型N、C。
構造体のエッジ{
     INT 次へ。
}エッジ[MAXN * 2 ]。
int型のヘッド[MAXN]、TOT;
無効{INIT()の
     ためのint型 I = 0 - [I] =ヘッドiが++; iが<= N)1 = 0 ;
}
無効アドオン(int型のu、int型V){
    EDGE [TOT] .TO = V?
    エッジ【TOT] .next = 頭部[U]。
    ヘッド[U]は ++ TOTを= 
}
INT [MAXN]。
int型IND [MAXN]。
無効 DFS(int型のu、int型ラ、int型最後){
    最後 = ([U]、最後の)を挿入。
    int型 ;〜I; I =ヘッド[U] I = エッジ[I] .next){
         int型 V = エッジ[I] .TO。
        もし(V == LA)続けます
        DFS(V、U、最後の);
    }
}
INT {main()の
    scanf関数(" %d個の%のD "、&​​N、&C)。
    初期化(); init();
    以下のためにint型私= 1 ; iが<= N; iが++)のscanf(" %dの"、および[I])。
    以下のためにint型 i = 1 ; iが<= N - 1 ; iは++ ){
         int型 Uを、V。scanf関数(" %d個の%d個"、&​​U&V);
        (V、U)を追加します。(V、U)を追加。IND [U] ++; IND [V] ++ ;
      //   coutの<< U << "" << V <<てendl; 
    }
     のためにint型 I = 1、N = iは<; iは++ ){
         場合(IND [I] == 1 ){
             DFS(I、 - 11 )。
        }
       // coutの<< I << "" << IND [i]は<<てendl; 
    }
    LL ANS = 0 以下のためにint型 i = 1 ; iは=サイズ<; iは++)ANS + = LEN [I] - LEN [FA [I]]。
    printf(" %LLDする\ n " 、ANS)。
    リターン 0 ;
}
コードの表示

 

おすすめ

転載: www.cnblogs.com/Hugh-Locke/p/11761394.html