問題の意味
長さnは小文字の文字列を考えます。どのように多くのあなたのは(も考慮交差点を含む)パリンドローム部分文字列の交点を求めています。
入力形式
最初の行は、文字列長n(1 <= N <= 2 ^ 6 * 10)と、第2行の文字列
出力フォーマット
サブストリングの数は%51123987パリンドロームと交差します
問題の解決策
Zhengnanzefan
あなたは私の最初と最後にばらばらパリンドロームサブストリング対数、事前回文配列の数を見つけることができます。
始まる回文配列私は、私の前に回文配列の後、最後に交差しません。
パリンドロームストリングを求めるmanacher前処理が最長である場合、J-1を開始する場合は、間隔が変更されるように、差分アレイを利用することができ、J(J <I)とそこから始まります。
統計への答えは、のみ元の文字列は、[1、i)はパリンドロームのサブストリングの最後に記録した統計合計の数として算出した読んだとき。
// の互いに素なパリンドローム配列番号求めて、変換を補完 する#include <ビット/ STDC ++ H.> 使用して名前空間STDと、 の#define LLロングロング CONST INT MOD = 51123987 ; のconst int型 INV = 25561994 ; CONST INT MAXN = 2000005 ; int型N-; LL ANS; INT PL [MAXN << 1。]; int型の L [MAXN << 1。 ]は、R [MAXN << 1。]; CHAR S [MAXN << 1。]、T [MAXN]; ボイドmanacher( ){ S [ 0 ] = ' + " ; 以下のために(int型 i = 1 ; iが< 2 *をN、I + = 2 ){ S [I] = ' #' 。 S [I + 1 ] = T [I / 2 ]。 } S [ 2 * N + 1 ] = ' #' 。 S [ 2 * N + 2 ] = ' - ' 。 S [ 2 * N + 3 ] = ' \ 0 ' 。 N =2 * N + 1 。 INT MX = 0、ID = 0 。 以下のために(int型 i = 1 ; iが<= N; iは++ ){ 場合(MX> = I)PL [I] =分(MX-I + 1、PL [ 2 * ID- I])。 他の PL [I] = 1 ; ながら PL [I] ++(S [I-PL [I]] == S [I [i]は、PLの+])。 場合(I [i]はPLを+ - 1 > MX)MX =私は、PLの+ [I] - 1、ID = I。 L [iが -PL [I] + 1 ] ++; L [I + 1 ] - 。 R [i]は++; R [Iは、PLの+ [I]] - 。 ANS =(ANS +(PL [I] >> 1))%MOD。// 原串回文串总数 // のprintf( "%dの"、S1 [i])と; } } int型のmain(){ scanf関数(" %のD "、&N) scanf関数(" %sの" 、T); manacher(); // のprintf( "%dの"、ANS)。 ANS =(ANS×(ans- 1)%のMOD)* INV%MOD。 // のprintf( "%dの"、ANS)。 LL合計= 0 ; 以下のために(int型 i = 1 ; iが<= N。 L [I] + = L [I- 1 ]、R [I] + = R [I- 1 ]。 もし(I&1)続けます。 ANS =(ANS-和* L [I])%MOD。 合計 =(和+ R [i])と%MOD。 } のprintf(" %のLLD "、(MOD + ANS%MOD)%のMOD)。 }
YYRは、私はそれを書いていない道を言います。。。。この方法では、理解しやすいです