/ * 各状態記憶最長一致長、および文字列マッチング処理の複数の最長一致の最小長取り 異なる場所とLCS1:LCS長寿命メンテナンス現在の最長一致長の一致長とすることができるが、複数文字列マッチング各ノード(即ち、接尾辞木)の状態情報を維持する必要がある ので、各状態のための2つの値のMAX、MINを保存することができ、各状態は、文字列の長さに対する最長一致を表し、すべてが一致していましたこの状態で最長一致文字列の最小長さ 背ボトムアップから接尾辞木を一致文字列の後に、最大値の更新 更新が最大最小完了した後に更新を * / の#include <ビット/ STDCを++。H > 使用して 名前空間STD; の#define MAXN 400005 構造体SAM { int型最後に、CNT; INT NXT [MAXN] [ 26である]、LEN [MAXN]は、リンク[MAXN]; SAMは、(){最後 = CNT = 1 ;} 無効に追加します(INT C){ int型 P =最後に、NP =最終++ =CNT; LEN [NP] = LEN [P] + 1 。 用(;!P && NXT [P] [C]; P = リンク[P]) NXT [P]、[C] = NP。 もし(!pは){リンク[NP] = 1。返す;} int型 Q = NXT [P]、[C]。 もし(LEN == LEN [Q] [P] + 1){リンク[NP] = Q。返す;} int型クローン= ++ CNT; リンク[クローン] = リンク[Q]。 LEN [クローン] = LEN [P] + 1 。 memcpy(NXT [クローン]、NXT [Q]、はsizeof NXT [Q])。 リンク[Q]=リンク[NP] = クローン。 用(; P && NXT [P] [C] == Q; P = リンク[P]) NXT [P]、[C] = クローン。 } int型[MAXN]最小値、最大値を[MAXN]、T [MAXN]、ID [MAXN]。 ボイドソート(){ ため(int型 I = 1を T [LEN [I]] ++; iが= CNTを<I ++)は、 用(int型 iは= 1 ; iが= CNTを<; I ++)はT [I] + = T [I- 1 ]。 以下のために(int型 i = 1 ; iは= CNTを<; I ++の)ID [T [LEN [I]] - ] = I。 用(int型 I = 1 =最小[i]はiが++; iが= CNTを<)LEN [i]は、 } ボイド更新(チャー *のS){ memsetの(最大、0、はsizeof 最大)。 INT今= 1、CUR = 0、レン= (S)strlenを。 以下のために(int型私= 0 ; iがレンを<; Iは++ ){ int型 P = S [I] - [ A ' 。 もし(NXT [今] [P]){ CUR ++ 。 今 = NXT [今] [P]。 } 他{ しばらく(!今&& NXT [今] [P]) になりました = リンク[今]。 もし(現在){ CUR = LEN [今] + 1 。 今 = NXT [今] [P]。 } 他{ CUR = 0 ;今= 1 。 } } マックス[今] = MAX(最大[今]、CUR)。 } のために(int型 = CNTのI; I> = 1 ; i-- ){ int型 TMP =ID [i]は、 マックス[リンク[TMP] = MAX(最大[リンク[TMP]、最大[TMP])。 } のために(int型 I = CNTを、I> = 1 ; i-- ) ミン[I] = 分(分[I]、最大[I])。 } int型CALC(){ int型 RES = 0 。 用(int型 I = 1 RES =;私は= CNTを<I ++)はMAX(RES、最小[I])。 リターンのres; } }、P。 チャーS [MAXN]。 INT (){主 CIN >> S。 int型のlen =STRLEN(S); 以下のために(int型 i = 0 ; iがLEN <; iは++)p.add(S [I] - [ A ' ); p.sort(); しばらく(scanf関数(" %sの"!、S)= EOF) p.update(S); COUT << p.calc()<< ENDL。 }