Good Bye 2015 D - New Year and Ancient Prophecy

問題リンク

TLで少しだけ話題になっていたのと、文字列アルゴリズムはこんなところにも使えて便利だから勉強しようという面で

 
dp[i][j] := i文字目からj文字で区切る場合の数

としよう。

そうすると、


dp[i][j] = \displaystyle \sum _ {k = 1} ^ {j - 1} dp[i - k][k]  \qquad (s[i - j : i - 1] \geq s[i : i + j - 1] ) \\

dp[i][j] = \displaystyle \sum _ {k = 1} ^ {j} dp[i - k][k]  \qquad (s[i - j : i - 1] < s[i : i + j - 1] )

であることは、明らかであろう。

でこの遷移そのものは累積和DPをつかえば、全体でO(N ^ 2)でできることもわかる。

さて問題は多倍長整数の大小比較である。ここがO(1)でできないと N \leq 5000と非常に大きいのでTLEする可能性が高い。

ここで使えるのがZ - Algorithmである。

というのもZ - Algorithmは先頭何文字が同じかを判定するアルゴリズムであるが、これはまさしく多倍長の大小判定そのものである(同じところの次の桁の大小比較をすればいいだけなので)

Z - Algorithmを使った大小比較の計算量は、前計算O(N ^ 2) で 判定は O(1)でできる。

以上でこの問題を解くことができました。

ちなみにRolling Hashを使うと O(N ^ 2 \log N )でできるが、Rolling Hashの定数倍はmodをとる関係でそこそこ重いので通る保証はあまりない…

提出コード

codeforces.com