len是以尾部为point[ i ]的最长回文长度,如果反着建就有以len为头的最长回文长度。相加可得,可以定义一个id来确定尾坐标与point之间的关系。
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 300000 , MAXK = 26;
char str[ MAXN + 5 ];
struct Palindrome_Automaton{
int Size = 0 //总节点
, Last , Root0 , Root1 , Trans[ MAXN + 5 ][ MAXK + 5 ] , Fail[ MAXN + 5 ];int id[MAXN];
long long Len[ MAXN + 5 ];
Palindrome_Automaton( ) {
Root0 = Size ++ , Root1 = Size; Last = Root1;
Len[ Root0 ] = 0 , Fail[ Root0 ] = Root1;
Len[ Root1 ] = -1 , Fail[ Root1 ] = Root1;
}
void Extend( int ch , int dex ) {
int u = Last;
while (str[ dex - Len[ u ] - 1 ] != str[ dex ] ) u = Fail[ u ]; //找到合格的后缀
if( !Trans[ u ][ ch ] ) { //无现成的边
int Newnode = ++ Size , v = Fail[ u ]; //防止取掉整串
Len[ Newnode ] = Len[ u ] + 2;
while (str[ dex - Len[ v ] - 1 ] != str[ dex ] ) v = Fail[ v ]; //给他找一个fail指针
Fail[ Newnode ] = Trans[ v ][ ch ] , Trans[ u ][ ch ] = Newnode;
}
Last = Trans[ u ][ ch ];
id[dex] = Last;
}
void Build() {
int len = strlen( str +1);
for( int i = 1 ; i <= len ; i ++ ) {
Extend( str[ i ] - 'a' + 1 , i );
}
}
}PAM,PAM1;
signed main( ) {
cin >>( str+1 );
int len = strlen(str+1);
PAM.Build();
reverse(str+1,str+len+1);
PAM1.Build();
long long ans = 0;
for (int i = 1; i < len; ++i) {
ans = max(ans,PAM.Len[PAM.id[i]] + PAM1.Len[ PAM1.id[len-i]]);
}
cout << ans;
return 0;
}