#include <cstdio>
#include <cstring>
#define NMax 505
using namespace std;
char String[NMax];
short N, AI[3*NMax][27], MaxS;
inline short Max (short a, short b)
{
if (a>b)
{
return a;
}
return b;
}
void Read ()
{
freopen ("palm.in", "r", stdin);
scanf ("%s", String);
N=(short)strlen (String);
}
void Update (short K, short L, short R, short P, short C, short V)
{
short Mid=(L+R)>>1;
if (L==R)
{
for (short c=C; c>=0; --c)
{
AI[K][c]=Max (AI[K][c], V);
}
return;
}
if (P<=Mid)
{
Update (K<<1, L, Mid, P, C, V);
}
else
{
Update ((K<<1)+1, Mid+1, R, P, C, V);
}
for (short c=0; c<=26; ++c)
{
AI[K][c]=Max (AI[K<<1][c], AI[(K<<1)+1][c]);
}
}
short Query (short K, short L, short R, short Q, short V)
{
short Mid=(L+R)>>1;
if (R<=Q)
{
return AI[K][V];
}
if (Q<=Mid)
{
return Query (K<<1, L, Mid, Q, V);
}
return Max (Query (K<<1, L, Mid, Q, V), Query ((K<<1)+1, Mid+1, R, Q, V));
}
void Solve ()
{
for (short i=N-1; i>=0; --i)
{
for (short j=N-1; j>i; --j)
{
if (String[i]!=String[j])
{
continue;
}
short CurrentS=2+Query (1, 0, N-1, j-1, (short)String[i]-(short)'a');
Update (1, 0, N-1, j, (short)String[j]-(short)'a', CurrentS);
MaxS=Max (MaxS, CurrentS);
}
Update (1, 0, N-1, i, (short)String[i]-(short)'a', 1);
}
}
void Print ()
{
freopen ("palm.out", "w", stdout);
printf ("%d\n", MaxS);
}
int main()
{
Read ();
Solve ();
Print ();
return 0;
}