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、 - 1、1 )。 } // coutの<< I << "" << IND [i]は<<てendl; } LL ANS = 0 。 以下のために(int型 i = 1 ; iは=サイズ<; iは++)ANS + = LEN [I] - LEN [FA [I]]。 printf(" %LLDする\ n " 、ANS)。 リターン 0 ; }