URL:https://www.luogu.org/problem/P3809
質問の意味:
辞書順にソートされた文字列のすべてのサフィックス。文字列の長さは、$ 1E6の$未満です。
ソリューション:
その後、原理は最初の開始位置は、2番目のキーワードとして$ I + 1 $最初のキーとして$ I $の接尾辞である、キーワードは、新しい最初のキーを取得するために結合される裸の接尾辞配列、$私は2番目の鍵として2 $を+、その後、乗算、続いて組み合わせます。特定の実装コードのコメントを参照してください。
参考ブログ:
https://www.cnblogs.com/victorique/p/8480093.html
https://www.luogu.org/blog/black-jokers/solution1-p3809
https://www.cnblogs.com/ezoiLZH/p/9607849.html
ACコード:
#include <ビット/ STDC ++ H.> 使用して名前空間STD; のconst int型MAXN = 1000005; 構造体接尾辞配列 { int型N-、M; int型税[MAXN]、ランク[MAXN]、TP [MAXN]、SA [MAXN]; // SAは[i]は= J、i番目の名前が最初からjのサフィックス(ただし、預金添字) //ランク[i]は= J、サフィックスjの初めから私は名前がある(と相反SA 、位置(値)) // TP [i]は、第二は、最初からキーワードサフィックスI jのである(第2のキーワードにSAアレイ当量は、格納されたインデックスである) //税[I] = J、Iは(基数ソートの値であるときにタブを有する)Jを有するキーワードの最初の数を表し ; CHAR CH [MAXN] //基数ソート)ボイドソート( { (I 0 = int型のために、私は< = M; ++ I)//は浴槽クリア ;税[I] = 0を 、対応するバレルのそれぞれに// I ++)は数から得られる; I <= N;(私は= int型1について私は最初のキーワードサフィックスが初段[i]の名前で、開始 //このランキングの接尾辞が税務ある[ランク[I]] ++税[ランク[I]] ; については、(int型I = 1; I <=メートル; ++ I)/ /プラスバケットの前で、ソートが完了し、ランキングを取得するには 税[I] + =税; [1-I。] について(I = N-をint型; i>は= 1; - I)からi //サフィックスは、2番目のキーワードTPの接尾辞である[I]、税[ランク[TP [I]]] = jの私は2番目の鍵である 接尾辞//単語最初のキーワードはそうjのサフィックスを持つ最初のキーワード、求めていると、すでに自分のランキングを知った後、基数ソートための接頭辞であり、入れ TPを対応@サフィックスのランキング[i]が減少ランクながら、記録されています。私は2番目のキーのサフィックスに最初のキー取るたびに 、これは最初のキーワードに応じてソートの第2の鍵、の同等と同じであるように、最後のキーワードに最初の//サフィックスを第二のハードル場合 //キーワードが同じではありませんした後、第1および第2のキーワードでソートされたことを確実にするために、この時点でより確か、最初の大きなキーワードです。 SA [税[順位[TP [I]]] - ] = TPの[I]; } BOOL CMP(int型、int型B、INT K) { // TPは今最後のランクであり、 //段落を上記[I-1] SAから意味[i]とSAから開始すると、同じ順位、かどうか接尾辞の始まりである Jの添加は比較ランキングは、第2の鍵であることを意味した後、同じトークンの後に//アイテム。交差なし保証 戻りTPを[A] == TP [B] && TP [A + K] == TP [B + K]; { N- = STRLEN(CH用+ 1)。 } get_saボイド() ランク[SA [1] = P = 1; // ソートで行わ新しいSAに記録された空きランク対応関係 (。; I <= N; INT I = 1 ++ I)のために 、M = MAX(M、ランク[I]は= CH [I]は- '0')、TP [I] = Iであり; //最初のラウンドASCIIコードキーを押し、第2プレス番号キー ソート(); //基数ソートの最初のラウンド のために(int型、P = 0、J = 1、P <N; J << = 1、M = P) { P = 0; //クリア するため(= I int型1; iは= <jの、iは++) TP [P ++] = N-I-J +; //以下Jのこれらの後者の添え字i、のみそれ自体、底面にので、第2の鍵の長さを低減することによって増大される (私は= int型1; iについて<= N; I ++)は IF(SA [I]> J) TPの[++ P] = SA [i]の-j ; // SA [I]> Jプルーフサフィックス長さI Jよりも大きい場合、TP [SA [i]は -j] サフィックスSAである[I] -j第2の鍵は、このしばらくまだオーダーのうち 一種(); //第二ラウンドと基数ソートを超えて スワップ(ランク、TP); // TP 役に立たない、我々はTPにコピーされた情報をランク付けします。空きランクながら 順位[SA [I] = CMP(SA [I]、SA [-I 1。]、J)P:++しますか? P; (I 2 = int型、iが<= N; ++ i)について } } }。 接尾辞配列のSA。 INTメイン() { //scanf("%d",&sa.n)。 scanf関数( "%sの"、sa.ch + 1)。 sa.get_sa(); (; I <= sa.n ++ iは1 = INT)のための 「「):のprintf( "%d個の%のC"、sa.sa [i]は、(I == sa.n '\ n'は); 0を返します。 }