传送门
题意:给定一个字符串,求出最长的双回文串长度。
思路:先跑一边Manacher,再求出每个字符所在回文串中,处在右侧且最长的子串中心,和处在左侧且最长的子串中心,最后拼接起来找最长的即可
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN = 11000000+5;
int n;
char a[MAXN], s[MAXN*2];
int len[MAXN*2];
int _left[MAXN*2], _right[MAXN*2]; //分别表示i所在回文串中,i处于右侧且最长的回文串中心,i处于左侧且最长的回文串中心
void manacher(){
//预处理
s[0] = '$'; s[1] = '#';
for(int i = 0; i < n; ++i){
s[2*i+2] = a[i];
s[2*i+3] = '#';
}
n = 2*n+2;
s[n] = 0;
//manacher
int max_right = 0, mid = 0;
for(int i = 1; i < n; ++i){
if(i < max_right) len[i] = min(len[2*mid-i], len[mid]+mid-i);
else len[i] = 1;
while(s[i+len[i]] == s[i-len[i]])
len[i]++;
if(len[i] > len[mid]){
max_right = i+len[i];
mid = i;
}
}
}
int main(){
cin >> a;
n = strlen(a);
manacher();
int cur = 1;
for(int i = 1; i < n; ++i){
while(cur <= i+len[i]-1)
_left[cur++] = i;
}
cur = n-1;
for(int i = n-1; i >= 1; --i){
while(cur >= i-len[i]+1)
_right[cur--] = i;
}
int ans = 0;
for(int i = 2; i < n-2; i = i+2){
ans = max(ans, i-_left[i]+1+_right[(i+2)]-(i+2)+1);
}
cout << ans << endl;
return 0;
}