#include<bits/stdc++.h>
using namespace std;
const int N=11000005;
char s[N<<1];
int n,p[N<<1];
//p[i]:以s[i]为中心的回文串的回文半径
//回文半径:对于a|b|a来说,其回文中心为'b',回文半径为"a|b"或"b|a"的长度,即3
//为什么叫半径?很显然,回文串一定是对称的(不然呢)
void input(){
char ch=getchar();
s[0]='~';//左边的哨兵节点(右侧的为\0)
s[n=1]='|';//插入隔板(强行将长度为奇数的情况转化为偶数的情况)
while(ch<'a' || ch>'z') ch=getchar();
while(ch>='a' && ch<='z'){
s[++n]=ch;
s[++n]='|';
ch=getchar();
}
}
int main(){
cin.tie(nullptr)->sync_with_stdio(false);
input();
int ans=0;
for(int i=1,r=0,mid=0;i<=n;i++){
//i,r,mid:当前扫描到的下标、已经确定的右边界、已经确定的右侧最靠右的回文串的对称中心
if(i<=r) p[i]=min(p[2*mid-i],r-i+1);
//核心思想当我们拓展到一个新字符时,不必重新从当前位置开始向左向右扫描,可以事先确定一部分回文半径
//若i在已确定的右边界内,其回文半径就是其对称点的回文半径(当然,不能越界)
while(s[i-p[i]]==s[i+p[i]]) p[i]++;//暴力拓展边界(最多拓展n次,且不回头,所以时间复杂度时O(n))
if(i+p[i]-1>r){//产生了新的右边界(注意,是闭区间)
r=i+p[i]-1;
mid=i;
}
ans=max(ans,p[i]);
}
cout<<ans-1<<'\n';
//一个回文串在在原串中的长度为L,经过转化后变为2L+1,其回文半径为L+1,所以答案要-1
return 0;
}