トピックの説明
英語の小文字 a、b、c、...y、z のみで構成される文字列 S が与えられた場合、S 内の最長の回文の長さを求めます。
文字列の長さは n です。
入力フォーマット
英語の小文字 a、b、c、⋯、y、z の行で構成される文字列 SS。
出力フォーマット
答えを表す整数。
入力サンプルと出力サンプル
#1 を入力してコピーします
ああ
#1 のコピーを出力します
3
指示/ヒント
1≦n≦1.1×107
アイデア:
回文文字列の総当たり検索:
1文字を中心として両側に広げます。
manacher アルゴリズムは、回文文字列を最適化したものです。
最初に考慮すべきことは、文字列のサイズです (偶数または奇数の場合があります)。
文字を追加するだけで、それらをすべて引き算して奇数にすることができます。
最初と最後に注目してください、1つは見張りの役割です。
P 配列は、中心を半径とする小さな回文文字列の長さを表します。
#define _CRT_SECURE_NO_WARNINGS 1
#include<bits/stdc++.h>
using namespace std;
const int N = 11000002;
int n, P[N << 1];
char a[N], S[N << 1];
void change() {
n = strlen(a);
int k = 0;
S[k++] = '$';
S[k++] = '#';
for (int i = 0; i < n; i++) {
S[k++] = a[i];
S[k++] = '#';
}
S[k++] = '&';
n = k;
}
void manacher() {
int R = 0, C;
for (int i = 1; i < n; i++) {
if (i < R) P[i] = min(P[(C << 1)-i] , P[C] + C - i);
else P[i] = 1;
while (S[i + P[i]] == S[i - P[i]]) P[i]++;
if (P[i] + i > R) {
R = P[i] + i;
C = i;
}
}
}
int main() {
scanf("%s", a);
change();
manacher();
int ans = 1;
for (int i = 0; i < n; i++) ans = max(ans, P[i]);
cout << ans - 1;
return 0;
}