タイトル説明
ストリングSが与えられ、そしてq問い合わせ時間、ストリングの各質問サイクル部最短ストリング。
考え
この質問は、それは少なくともlojデータはい、がん問題にする必要があり、がんの問題です。私は2つのアイデアを、93ポイント、97ポイントのリードを読み出す加速し、加速しないを持っています。
まず、文字列のループ部の最小要件は、そのプレフィックス長要因を列挙することは明らかです。しかし、これは明らかにTになり、私たちは、最適化を検討してください。
我々は、すべての文字の数が急速にサブストリング内で決定、①を前処理することによって考慮することができ、及び文字の数が最小サイクル部はすべての文字の数の共通因数である必要があり、その後、サイクル部の最小数である必要があります因子の共通因子は、循環部させることが可能です。だから我々は、[1列挙 ループ部は、答えを更新するかどうかを確認するために、]。最後の93分。
②最初の練習走行は、過去を列挙していない理由は、あまりにも多くの州がある場合に役に立たないですが、それは、最適化を継続することは困難である、我々はオリジナルのアイデアからやり直してください。私たちは、最小サイクルの長さのセクションをしたい、それはまた、複数のループ部でなければなりません。私たちはまず、元の文字列の長さの直線ふるいの数の最小の素因数を削除します。LENを縮小、各品質係数を試みるで割っ決定品質係数、であり、各々が長さの素因数分解を求め、各サブストリングクエリの後、最終的な答えは、最小円形断面です。
コード(方法a、93分)
#include <ビット/ STDC ++ H> 使用して 名前空間STDを、 typedefの符号なしの長い 、長い目。 CONST眼P = 131、MAXN 5E5 + = 10 。 チャーS [MAXN]。 目の合計[MAXN]電源[MAXN]年。 [MAXN] [F見30 ]。 f_hash眼(眼、眼R) { リターン(眼)和[R] -sum 1- [ 1 ] *電力[L + R- 1 ]。 } アイGCD(アイX、眼Y) { リターンのy == 0 X:GCD(Y、Xの%のY)。 } ボイド検査(眼、眼のR目LEN) { もし(f_hash(L、R-LEN)== f_hash(L + LEN、R)) ANS = 分(ANS、LEN)。 } )(読み取りULL { ULL RET = 0、W = 1 。 チャー CH = GETCHAR()。 一方、(CH < ' 0 ' || CH> ' 9 '){ 場合(CH == ' - ' = W) - 1 ; CH = GETCHAR();} 一方(CH> = ' 0 ' && CH <= ' 9 '){RET = RET * 10 + CH- '0 ' ; CH = GETCHAR();} 戻りのRET *のW。 } int型のmain() { ULL N。 N = 読み取ります(); 取得(S + 1 )。 電力[ 0 ] = 1 ; ため(ULL i = 1 ; iが<= N; iは++ ) { 和[i]は =和[I- 1 ] * P +(S [I] - ' ' + 1 )。 電源[I] =電力[I- 1 ] * P。 } ため(ULL I = 1 ; iが<= N; iが++ ) { ため(ULLのJ = 1 ; J <= 26 ; J ++ ) [I] [J] F = fは[I- 1 ] [J]。 F [i]は[S [I] - ' ' + 1 ] ++ ; } ULL Q。 Q = 読み取り(); 一方、(q-- ) { ULLのL、R。 L =読み取る(); R = リード()。 ULL LEN = R-L + 1、vgcd = R-L + 1 。 用(ULL I = 1;私は= < 26 ; iは++ ) vgcd = GCD(vgcd、F [R] [I] -f [1- 1 ] [I])。 ANS = 1E9; ため(ULL i = 1 ; iは++; iは<= vgcd * ) であれば(vgcd%のI == 0 ) { チェック(L、R、LEN / I)。 チェック(L、R、lenが /(vgcd / I))。 } のprintf(" %LLUする\ n " 、ANS)。 } 戻り 0 。 }
コード(正の解、アウト)
#include <ビット/ STDC ++ H> 使用して 名前空間STDを、 typedefの符号なしの長い 長いULL。 CONST ULLのP = 47、MAXN = 5E5 + 10 。 チャーS [MAXN]。 ULL和[MAXN]、パワー[MAXN]、ANS、YS [MAXN]、プライム[MAXN]、NXT [MAXN]。 BOOL [MAXN]使用。 ULL f_hash(ULLのL、ULL R) { リターン(ULL)和[R] -sum 1- [ 1 ] *電力[R-L + 1 ]。 } ブールチェック(ULLのL、R ULL、ULL LEN) { 戻り f_hash(L、R-LEN)== f_hash(L + LEN、R)。 } ULLリード() { ULL RES= 0、W = 1 。 チャー CH = GETCHAR()。 一方、(CH < ' 0 ' || CH> ' 9 '){ 場合(CH == ' - ' = W) - 1 ; CH = GETCHAR();} 一方(CH> = ' 0 ' && CH <= ' 9 '){RESの=(RES << 3)+(RES << 1)+(CH ^ 48)、CH = GETCHAR();} 戻り RES * W。 ライト(ULLのX) { (X> 9)書き込み(X / 10 )。 putchar(X%10 ^ 48 )。 } ボイドのwriteln(ULL x)から { 書き込み(X)。 putchar(' \ nを' ); } ボイドPRI() { ULLのK = 0 。 用(ULL I = 2 ; I <= MAXN; iは++ ) { 場合(!使用[I]) { プライム[ ++ K] = I。 NXT [I] = I。 } のために(INT J = 1 ; J <= K && iは素数を* [J] <= MAXNあり、j ++ ) { ULL M = i *が素数[j]を。 中古[M] = 1 。 NXT [M] = プライム[J]。 もし(I%、プライム[J] == 0)ブレーク。 } } } int型のmain() { ULL N = 読み取ります()。 scanf関数(" %sの"、S + 1 )。 電力[ 0 ] = 1 ; ために(ULL i = 1 ; iが++; iが<= N ) { 和[I] =和[I- 1 ] * P +(S [I] - ' ' + 1 )。 電源[I] =電力[I- 1 ] * P。 } PRI()。 ULL Q = 読み取り()。 一方、(q-- ) { ULLさL =読み取る()、R = 読み取り()。 ULL LEN = R-L + 1、CNT = 0 。 一方、(LEN!= 1 ) { YS [++ CNT] = NXT [LEN]。 LEN / = NXT [LEN]。 } LEN = R-L + 1 。 以下のために(int型 i = 1 ; iは= CNTを<; iは++ ) { int型 TMP = LEN / YS [i]は、 もし(チェック(L、R、TMP)) LEN = TMP。 } のwriteln(LEN)。 } 戻り 0 。 }