タイトル説明
トラウトは、グランドマスターの熟練した魔法で、そして今、彼は、呪文の束を持っている唯一の文字列sである(1 <= | | S <= 300000) 小文字で構成される。
この文字列は、各位置のための午前1時クラスA損傷の原因となり、異なる(すなわち、開始位置(例えば、「AA」つのみ「」パリンドロームサブストリングと同じオペレータからの位置別の開始、)各部分が異なるパリンドロームであります異なる別の「AA」2つの異なる位置がある「」回文ストリング)回文構造部分文字列一時クラスBは、破損の原因となりますで説明したようにも考慮。
トラウトはタルシシュの魔法は多くの被害点Aクラス、Bクラスどのように多くのポイントのダメージを与えます知ってほしいです。
トラウトは今あなたにこのタスクを置きます。
入力形式
文字列がね。
出力フォーマット
二つの整数、B、クラスA損傷点の代表、B点タイプBダメージ。
サンプル
サンプル入力1
xibobix
サンプル出力1
7 10
データ範囲とヒント
1 <= | S | <= 300000。
文字列が小文字のみが含まれています
のは、この質問の最初の部分を考えてみましょう。サブストリングの異なる番号の最初の回文ツリーから構築容易に考えられる数は、パリンドロームパリンドロームツリーノード2(奇数と偶数の除去)です。
私たちは第二部を考えてみましょう。私たちの木が、我々はSの数を計算していると仮定すると、インクリメンタル回文構造であるため、私たちは、プレフィックスとの考えを使用し、その後、S + CのSC番号の数は回文配列番号の末尾にあります、最長接尾語のパリンドローム長さがフェイル2鎖(奇数および偶数を除きます)。だから我々は両方のケースで答えを見つけます。
書式#include <iostreamの> の#include <cstdioを> する#include <CStringの> 使用して 名前空間をSTD。 const int型 N = 400000 ; チャーS [N]。 int型レンズ; 長い 長いANS; 名前空間Plalindromic_Tree { 構造体ノード{ INTゴー[ 26 ]。 INT lenは、失敗します。 長い 長いfail_len。 } PT [N]。 int型 LST = 0、TOT = 0 ; INT CNT [N]。 空のビルド(){ S [ 0 ] = - 1 。 PT [ ++ TOT] .LEN = - 1 。 PT [ 0 ] .fail = PT [ 1 ] .fail = 1 。 PT [ 1 ] .fail_len = 1 。 PT [ 0 ] .fail_len = 2 。 } int型の追加(int型 C、INT N){ int型、P = LST。 一方、 (S [N - PT [P] .LEN - 1!] = S [N])P = PT [P] .fail。 もし(!PT [P] .GO [C]){ int型 V = ++ TOT、K = PT [P] .fail。 PT [I] .LEN = PT [I] .LEN + 2 。 一方、(S [N - EN [A] .LEN - 1!] = P [N])= EN [A] .failと、 PT [V] .fail = PT [K] .GO [C]。 PT [V] .fail_len = PT [PT [K] .GO [C] fail_len +。1 。 PT [P] .GO [C] = V。 } CNT [PT [P] .GO [C]] ++ ; リターン LST = PT [P] .GO [C]。 } } 使用して 名前空間Plalindromic_Treeと、 INT メイン(){ scanf関数(" %S "、S + 1 )。 レンズ = strlenを(S + 1 )。 ビルド(); 以下のために(INT iが= 1 ; I <=レンズ; I ++ ){ ANS + = PT [追加(S [I] - ' '、I)] fail_len - 。2 。 } coutの << TOT - 1 << " " << ANS; リターン 0 ; }