この問題を解くうえでは以下の事実が重要になります。
上記の事実を用いると、この問題は以下のような手順で解くことができます。
Manacher's Algorithm を用いて各位置の最長回文半径 を求める。
について降順に探索する。連想配列と Rolling Hash を用いて、ハッシュごとの個数を記録する。
上記の手順により、それぞれの回文の出現回数が分かり、このアルゴリズムは連想配列に C++ の map などを用いると で動作するためこの問題を高速に解くことができました。
追記: Palindromic Tree を用いることによってそのままこの問題を解くことができるようです。
文字列の長さが の場合
現れる回文の種類数は 種類である。
末尾に文字を追加した場合に、新たに現れる回文の種類数が高々 種類であることを示す。
文字列に新たに文字を追加した場合に新たに現れる回文は、末尾を端とする回文になる。
ここで、回文が 種類増えると仮定すると、長さが大きい方の回文に必ず長さ小さい方の回文が連続する部分列として含まれるため矛盾する。