P3805 [テンプレート] manacher アルゴリズム

トピックの説明

英語の小文字 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;

}

おすすめ

転載: blog.csdn.net/zhi6fui/article/details/128735247