質問A:お香の文字列
制限時間:1秒 メモリ制限:512メガバイト
フェイス質問
彼は公に質問に直面して減少しました。
問題の解決策
文字列は、ヒトデ......正の解KMPを食べることができますが、私は233333水の上にハッシュを使用します。
小さな文字列に分割かどうかを確認するために、一致する文字列を指示します。列挙型の長さは、小規模から大規模まで、除数をスキップしないで、除数は、その後一致しています。
直接前処理およびプレフィックスが終了されるだろうハッシュに従事。
コード:
#include <ビット/ STDC ++ H> に#define INT長い長い INT RINTレジスタ#defineする の#define ULLのunsigned long長い 名前空間stdを使用。 const int型Z = 2333; INT T、N、M、ANS、LEN、BLO。 ULL HS [1000006]、JZ [1000006]。 チャーCH [1000006]。 _ok BOOL; 署名されたメイン() { // freopenは( "ex_ccx2.in"、 "R"、STDIN)。 // freopenは( "my.out"、 "W"、STDOUT)。 scanf関数( "%のLLD"、&T)。 一方、(T--) { scanf関数( "%LLD%LLD%s"は、&N、&M、CH + 1); JZ [0] = 1; (M == 1){場合のprintf( "%LLDする\ n"、n-1)は、継続;} ブールTE = 1。 (; I <= M ++ iはRINT I = 1)のために { 'A' - HS [I] = HS [I-1] * Z +(CH [I] 1); (もし!CH [I] = 'A')、TE = 0; SW [I] = J [I-1] * Z。 } IF(TE){のprintf( "%LLDする\ n"はn * M-1);続ける;} もし、(N×m個<= 1000000) { ANS = 0; JZ [0] = 1; 用(RINT I = 1; I <= N; ++ I) のために(RINTのJ = 1; J <= M; ++ j)は { RINT LIN =(I-1)* M + J。 HS [LIN] = HS [LIN-1] * Z +(CH [J] - '+ 1)。 JZ [LIN] = JZ [LIN-1] * Z。 } ため(RINT i = 1; iがn×m個の<; ++ I) IF(HS [I] == HS [N×m個] -HS [N * MI] * JZ [i])とANS = I。 printf( "%LLDする\ n"、ANS)。 持続する; } LEN = 0、BLO = 0。 用(RINT i = 1; iが<=(M / 2); ++ I) { IF(m個%I = 0!)継続; _ok = 1。 用(RINTのJ = 2、J <=(M / I); ++ j)は もし((HSは[i *が(J-1)] - !HS [i *は(J-2)] * JZ [I])=(HS [J * i]は-hs [i *が(J-1)] * JZ [I])){_ = 0 OK;ブレーク;} もし(_ok){LEN = I、BLO = M / LEN;ブレーク;} } printf( "%のLLDを\ n"、(N-1)* M +(BLO-1)* LEN)。 } 0を返します。 }