/*
* Rezolvarea naiva in N^3.
*
* Se putea si mai rapid in N^2 folosind doua cozi. In prima bagam primul caracter si in a doua urmatorul.
* Apoi pentru a creste lungimea bagam in prima coada primul caracter din a doua coada, iar aceasta
* primea inca 2 caractere (daca mai existau). La fiecare scoatere-bagare se actualizau doua numere
* pe post de hashuri. Aceste doua hashuri se comparau in O(1) folosind `==` astfel scutind inca o dimensiune.
*
* Calcularea numerelor se facea astfel: se scadea din caracterul curent caracterul 'A' ('A' < 'a') si se aduna la suma.
* Inainte de adunare suma era inmultita cu 100 (pentru evitarea coliziunilor evidente) pentru prima suma (specifica primei cozi).
* Din a doua suma se scadea valoarea primului caracter si se adunau pe rand primul caracter la puterea `p` si al doilea la puterea `p` + 1.
* Unde `p` reprezinta numarul de caractere din prima coada - 1 (adica jumatate de palindrom).
*
* Deoarece sumele sunt foarte mari se facea modulo cu o constanta destul de mare si pentru evitarea coliziunilor mai putin evidente
* se foloseau vreo `k` constante (3-6) diferite pentru a compara sumele intre ele, astfel crescand acuratetea.
* Complexitatea finala devenea O(KN^2).
*/
#include <iostream>
#include <string>
using namespace std;
int maxPal; // dimensiunea maxima
string str, pal; // sirul sursa, palindromul maxim
void solve()
{
/**
* Pentru fiecare pozitie si lungime se genereaza o subsecventa
* ce se compara cu ea insasi pornind din extremitati.
* Probabil daca se genereaza si inversul acesteia dureaza ceva mai mult
* chiar daca complexitatea teoretica ramane aceeasi.
*/
for (int pos = 0; pos < str.size(); ++pos) {
for (int len = 1; len <= str.size() - pos; ++len) {
string sub = str.substr(pos, len);
bool isPal = true;
for (int i = 0; i < len / 2 && isPal; i++) {
if (sub[i] != sub[len - i - 1]) isPal = false;
}
if (isPal && len > maxPal) {
maxPal = len;
pal = sub;
}
}
}
}
int main()
{
cin >> str;
solve(); // rezolvam
cout << pal;
return 0;
}