質問は、表面:
接尾辞配列(SA)は、通常二倍または我々の議論の範囲を超えているDC3アルゴリズム、重要なデータ構造です。
この問題では、我々は、高速行を使用する場合、ハッシュは、単純なバイナリで実現O (N- L O G 2 N- )接尾辞配列を探しているO(Nlog2N)。
具体的には、長さの文字列のn S(添字0〜N-1)が与えられると、我々は整数K(使用でき0 ≤ K < NサフィックスS(0≦k個の文字列Sを<N) 〜N-1)。
すべてのサフィックス文字列S辞書式順序に従ってランク付け添え字iは、[i]はSAと呼ばれています。
さらに、我々は接尾ランキング添え字i-1、iの順位をされて検討し、最長の共通のプレフィックスの長さは、両方の[i]の高さと呼ばれます。
私たちの仕事は、2つの配列SAと高さを見つけることです。
入力形式
長さ30万を超えていない文字列を入力します。
出力フォーマット
最初のラインアレイSA、スペースで区切られた隣接する二つの整数。
第二のラインアレイの高さ、スペースで区切られた隣接する二つの整数は、我々は、[1] = 0の高さを必要とします。
サンプル入力:
ponoiiipoi
出力例:
9 4 5 6 2 8 3 1 7 0 0 1 2 1 0 0 2 1 0 2
ソリューション:
2つの星の最長プレフィックスサフィックス初めの2、書き込みのソートするソート機能に応じて、
書式#include <iostreamの> の#include <アルゴリズム> 書式#include <CStringの> に#define ULL符号なしの長い長い 使用して 名前空間はstdを、 CONST ULLの基地 = 131 。 constの ULL INT_MIN = - 1E6; ULL H [ 300010 ]、P [ 300010 ]。 int型の SA [ 300010 ]。int型のn; チャー STR [ 300010 ]。 ULL GET(int型 L、INT R) { 戻り H [R] -h [1- 1] * P [R-L + 1 ]。 } INT get_max(int型、int型B) { int型の L = 0。INTの R =分(N-A + 1、N-B + 1 )。 一方、(L < R) { int型ミッド=(R + L + 1)>> 1 。 もし(取得(、A +ミッド1!)= 取得する(B、B +ミッド1))、R =ミッド1 。 他 リットル = ミッド; } 戻りL。 } BOOL CMP(int型 A、int型 B)// ソート機能 { int型 L = get_max(A、B); int型 > N-INT_MIN :? STR [A + AV = A + L L]; int型 BV = B + L> N-? INT_MIN:STR [B + L]は、 戻り AV < ; //昇順; BVを } int型のmain() { scanfの(" %のS "、STR + 1 ;) N- = STRLEN(STR + 1); P [ 0 ] = 。1 ; のための(INT I = 1 ; I <= N; I ++は) { H [I] = hの[I- 1 ] * 基底 + STR [I] - ' ' + 1 。 P [I] = P [I- 1 ] * 基地; SA [I] = I。 } ソート(SA + 1、SA + N + 1 、CMP)。 以下のために(int型 i = 1 ; iが<= N; iは++)のprintf(" %dの"、SAを[I] - 1 )。 プット("" ); 以下のための(int型 I = 1私は++; iが<= N) { もし(I == 1)のprintf(" 0 " )。 他 のprintf(" %dの"、get_max(SA [i]は、SA [I- 1 ]))。 } プット("" )。 リターン 0 ; }