異なる部分文字列の数
トピックの背景
NOIは愚かな虐待を受けているので、それは、このような問題に遭遇したので、YJQ準備こんにゃくは、文字列について知ることができます。
タイトル説明
あなたは長さN、異なるサブストリングの必要な数の文字列を与えます
そして二つのサブ文字列がある場合にのみ、同じ長さまたは同じ長さではなく、いずれか一方と同じがない場合、我々は、二つの異なるサブストリングを定義します。
定義された部分文字列:文字列の連続した文字の元の文字列
入力形式
整数Nの最初の行
N分析に代表される、次の行の文字列
出力フォーマット
異なるサブストリングの数を表す整数を行
サンプル入力と出力
入力#1
。5
aabaaの
出力#1
。11
入力#2
。3
ABAの
出力#2
。5
説明/ヒント
使用して、64ビット整数を出力します
(具体的には、C ++やC選手が長い長い、パスカルプレイヤーがInt64型を使用するタイプを使用します)
入力ファイルが大きすぎるため、読み取ることが非常に効果的な方法を使用して(具体的には、C ++やCプレイヤーがCINを使用しない、パスカルプレイヤーがコントロールしていません)
データの30%、N \ル1000年N ≤ 。1 0 0 0
データの100%にN \ル^ 10 5 N ≤ 。1 0 。5
参考ブログ:https://www.luogu.org/blog/Elaborate/solution-p2408
#include <ビット/ STDC ++ H> のconst int型 N = 4E5 + 50 。 使用して 名前空間はstdを、 構造体接尾辞配列 { INT SA [N]、順位[N]、高さ[N]、CNT [N]、A [N]、A2 [N]、N、M、*、X * Y。 ボイドソート() { ため(int型 i = 0 ; iがmを<; iは++)CNTを[I] = 0 ; 以下のために(int型 i = 0 ; iがN <、iは++)CNT [X [I]] ++ ; 用(int型 i = 1 ; iがmは<; I ++)はCNT [I] + = CNT [I- 1 ]。 以下のための(int型 I = N- 1を、I> = 0 ; i--)のSA [ - CNT [X [Y [I]]]] = Y [i]は、 } ボイドビルド(CHAR * sで、int型C_SIZE) { N = STRLEN(S)。 M = C_SIZE。 X = A1。 Y = A2。 以下のために(int型 i = 0 ; iがn <; iは++)X [I] = sの[I]、Y [i]は= I。 X [N] = Y [N] = - 1 。 ソート(); 用(int型のk = 1 ; K <= N; kは<< =1 ) { int型、P = 0 。 用(int型 Y [P ++] =; iがN <I ++はiはNK =)をI。 以下のために(int型 i = 0 ; iは<N; iは++)場合(SA [I]> = K)Y [P ++] =のSA [i]は- kは、 ソート(); P = 0 。 STD ::スワップ(X、Y) X [SA [ 0 ] = 0 ; 用(int型 iは= 1 ; iがN <I ++は) { 場合(Y [SA [I] = Y [SA [1-!1!] || Y [SAの[I] + K] = Y [SA [I- 1 ] + K])p ++ 。 X [SA [I] = P。 } もし(P + 1 > = N)、ブレーク。 M = P + 1 。 } のための(int型 I = 0 ; iがN <; I ++)は、ランク[SA [I] = I。 高さ[ 0 ] = 0 ; int型のk = 0 。 以下のために(int型 i = 0 ; iがn <; iは++ ) { 場合(K)k-- 。 もし(ランク[I] == 0)続けます。 int型 J = SA [ランク[I] - 1 ]; 一方(iは+ K <N && J + K <N && S [I + K] == S [J + K])は、k ++ ; 高さ[順位[I] = K。 } } } SA。 INT メイン() { チャー S [N] = { 0 }。 長い 長いLEN。 scanf関数(" %D%S "、&LEN、S); SA.build(S、256 )。 長い 長い ANS =(+ lenのLENの* 1)/ 2; 以下のために(int型 i = 1 ; iがLEN <; iは++ ) { ANS - = SA.height [I]。 } のprintf(" %LLDする\ n "、ANS)。// 返す 0 ; }