問題にチャレンジして、ユーザー同士で解答を教え合ったり、コードを公開してみよう!
前回まで、回文の性質を利用した効率的な最長回文半径の計算方法について学んできました。これを利用して、各中心について回文の性質を利用して最長回文半径を効率的に更新していけば、最長回文半径を高速に求めることができます。このように、回文の性質を利用して時間計算量 O(|s|) で計算するアルゴリズムを Manacher のアルゴリズムといいます。
では、実際に Manacher のアルゴリズムを実装してみましょう。
最長回文半径 p[i] を求める単純なアルゴリズムは、以下のようなものでした。
for i = 0 から |s| - 1 まで:
while 0 <= i - p[i] かつ i + p[i] < |s| かつ s[i - p[i]] == s[i + p[i]]:
p[i]++;
j = 0
for i = 0 から |s| - 1 まで:
if i < j + p[j]:
p[i] = min(p[j - (i - j)], j + p[j] - i)
if j + p[j] <= i + p[i]:
while 0 <= i - p[i] かつ i + p[i] < |s| かつ s[i - p[i]] == s[i + p[i]]:
p[i]++;
j = i
s
s の 1, 2, 3, ..., |s| 番目の文字を中心としたときの最長回文半径を、改行区切りで上から順に出力してください。
また、末尾に改行を入れ、余計な文字を含んではいけません。
すべてのテストケースにおいて、以下の条件をみたします。
・ 1 ≦ |s| ≦ 100000 = 10^5
・ s は英小文字のみからなる文字列
arewenewera
1
1
1
2
1
6
1
2
1
1
1