#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 300005;
struct PAM{//回文树
int next[maxn][26],fail[maxn],len[maxn],cnt[maxn],S[maxn];
// 一个结点一个本质不同的回文串
//len[i] 表示回文串i的长度
// next[i][c]编号为i的节点表示的回文串在两边添加字符c以后变成的回文串的编号(儿子)。
//cnt[i] 节点i表示的本质不同的串的个数
//(建树时求出的不是完全的,最后重新统计一遍以后才是正确的)。
// fail[i] 节点i失配以后跳转不等于自身的节点i表示的回文串的最长后缀回文串
//last 新添加一个字母后所形成的最长回文串表示的节点
// S[i] 第i次添加的字符(一开始设S[0] = -1,也可以是任意一个在串S中不会出现的字符)
//2~id-1 添加的结点 n 添加的字符个数
int id,n,last;
int newnode(int x){
for(int i=0;i<26;i++){
next[id][i]=0;
}
cnt[id]=0;
len[id]=x;
return id++;
}
void init(){
id=0;
newnode(0);
newnode(-1);
fail[0]=1;
S[0]=-1;
last=n=0;
}
int getfail(int x){
while(S[n-len[x]-1]!=S[n]) x=fail[x];
return x;
}
void Insert(int c){
c-='a';
S[++n]=c;
int cur=getfail(last);
if(!next[cur][c]){
int now=newnode(len[cur]+2);
fail[now]=next[getfail(fail[cur])][c];
next[cur][c]=now;
}
last=next[cur][c];
cnt[last]++;
}
ll getsum(){//自下向上更新
ll ans = 0;
for(int i=id-1;i>=0;i--){
cnt[fail[i]]+=cnt[i];
ans = max((ll)cnt[i]*(ll)len[i],ans);
}
return ans;
}
}pam;
char s[maxn];
int main()
{
scanf("%s",s);
int len = strlen(s);
pam.init();
for(int i=0;i<len;i++)
{
pam.Insert(s[i]);
}
printf("%lld",pam.getsum());
return 0;
}