#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> ii;
const int INF = 1e9;
const ll LINF = 1e18;
template<typename T>
void maximize(T& a, const T& b) {
if (a < b) a = b;
}
const int p = 31;
const int MOD = 1e9 + 9277;
const int N = 1e6 + 5;
int n;
string s;
int p_pow[N], inv_p_pow[N];
int h[N], rev_h[N];
int binpow(int a, int b) {
int ans = 1;
for (; b > 0; b >>= 1) {
if (b & 1) ans = 1ll * ans * a % MOD;
a = 1ll * a * a % MOD;
}
return ans;
}
void precompute() {
p_pow[0] = 1;
for (int i = 1; i <= n; i++) {
p_pow[i] = 1ll * p_pow[i - 1] * p % MOD;
}
inv_p_pow[n] = binpow(p_pow[n], MOD - 2);
for (int i = n - 1; i >= 0; i--) {
inv_p_pow[i] = 1ll * inv_p_pow[i + 1] * p % MOD;
}
h[0] = rev_h[0] = 0;
for (int i = 1; i <= n; i++) {
h[i] = (1ll * h[i - 1] * p + (s[i] - 'a' + 1)) % MOD;
rev_h[i] = (rev_h[i - 1] + 1ll * p_pow[i - 1] * (s[i] - 'a' + 1) % MOD) % MOD;
}
}
int getHash(int l, int r) {
return (h[r] - 1ll * h[l - 1] * p_pow[r - l + 1] % MOD + MOD) % MOD;
}
// Giá trị hash của xâu s[l..r] sau khi đảo ngược
int getRevHash(int l, int r) {
return 1ll * (rev_h[r] - rev_h[l - 1] + MOD) % MOD * inv_p_pow[l - 1] % MOD;
}
bool isPalin(int l, int r) {
return (getHash(l, r) == getRevHash(l, r));
}
// Với mỗi tâm đối xứng center thì tìm độ dài "bán kính" lớn nhất
ii maxOddLength() {
ii best = {0, 0};
for (int center = 1; center <= n; center++) {
int l = 0, r = min(center - 1, n - center), ans = 0;
while (l <= r) {
int mid = (l + r) >> 1;
if (isPalin(center - mid, center + mid)) {
ans = mid;
l = mid + 1;
}
else {
r = mid - 1;
}
}
maximize(best, make_pair(2 * ans + 1, center - ans));
}
return best;
}
ii maxEvenLength() {
ii best = {0, 0};
for (int center = 1; center + 1 <= n; center++) {
int l = 1, r = min(center, n - center), ans = 0;
while (l <= r) {
int mid = (l + r) >> 1;
if (isPalin(center - mid + 1, center + mid)) {
ans = mid;
l = mid + 1;
}
else {
r = mid - 1;
}
}
maximize(best, make_pair(2 * ans, center - ans + 1));
}
return best;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> s;
n = s.size();
s = ' ' + s;
precompute();
// ans.first = độ dài xâu con đối xứng dài nhất
// ans.second = vị trí bắt đầu của nó trong xâu s
ii ans = max(maxOddLength(), maxEvenLength());
string t = s.substr(ans.second, ans.first);
cout << t << '\n';
}
I2luY2x1ZGUgPGJpdHMvc3RkYysrLmg+IAoKdXNpbmcgbmFtZXNwYWNlIHN0ZDsgIAoKdHlwZWRlZiBsb25nIGxvbmcgbGw7ICAKdHlwZWRlZiBwYWlyPGludCwgaW50PiBpaTsgIAoKY29uc3QgaW50IElORiA9IDFlOTsgIApjb25zdCBsbCBMSU5GID0gMWUxODsgIAoKdGVtcGxhdGU8dHlwZW5hbWUgVD4Kdm9pZCBtYXhpbWl6ZShUJiBhLCBjb25zdCBUJiBiKSB7CglpZiAoYSA8IGIpIGEgPSBiOyAgCn0KCmNvbnN0IGludCBwID0gMzE7ICAKY29uc3QgaW50IE1PRCA9IDFlOSArIDkyNzc7IApjb25zdCBpbnQgTiA9IDFlNiArIDU7IAoKaW50IG47IApzdHJpbmcgczsgCmludCBwX3Bvd1tOXSwgaW52X3BfcG93W05dOyAKaW50IGhbTl0sIHJldl9oW05dOyAKCmludCBiaW5wb3coaW50IGEsIGludCBiKSB7CglpbnQgYW5zID0gMTsgCglmb3IgKDsgYiA+IDA7IGIgPj49IDEpIHsKCQlpZiAoYiAmIDEpIGFucyA9IDFsbCAqIGFucyAqIGEgJSBNT0Q7ICAKCQlhID0gMWxsICogYSAqIGEgJSBNT0Q7IAoJfQoJcmV0dXJuIGFuczsKfQoKdm9pZCBwcmVjb21wdXRlKCkgewoJcF9wb3dbMF0gPSAxOyAKCWZvciAoaW50IGkgPSAxOyBpIDw9IG47IGkrKykgewoJCXBfcG93W2ldID0gMWxsICogcF9wb3dbaSAtIDFdICogcCAlIE1PRDsgCgl9CgoJaW52X3BfcG93W25dID0gYmlucG93KHBfcG93W25dLCBNT0QgLSAyKTsgCglmb3IgKGludCBpID0gbiAtIDE7IGkgPj0gMDsgaS0tKSB7CgkJaW52X3BfcG93W2ldID0gMWxsICogaW52X3BfcG93W2kgKyAxXSAqIHAgJSBNT0Q7IAoJfQoKCWhbMF0gPSByZXZfaFswXSA9IDA7ICAgCglmb3IgKGludCBpID0gMTsgaSA8PSBuOyBpKyspIHsKCQloW2ldID0gKDFsbCAqIGhbaSAtIDFdICogcCArIChzW2ldIC0gJ2EnICsgMSkpICUgTU9EOyAKCQlyZXZfaFtpXSA9IChyZXZfaFtpIC0gMV0gKyAxbGwgKiBwX3Bvd1tpIC0gMV0gKiAoc1tpXSAtICdhJyArIDEpICUgTU9EKSAlIE1PRDsgCgl9Cn0KCmludCBnZXRIYXNoKGludCBsLCBpbnQgcikgewoJcmV0dXJuIChoW3JdIC0gMWxsICogaFtsIC0gMV0gKiBwX3Bvd1tyIC0gbCArIDFdICUgTU9EICsgTU9EKSAlIE1PRDsgCn0KCi8vIEdpw6EgdHLhu4sgaGFzaCBj4bunYSB4w6J1IHNbbC4ucl0gc2F1IGtoaSDEkeG6o28gbmfGsOG7o2MKaW50IGdldFJldkhhc2goaW50IGwsIGludCByKSB7CglyZXR1cm4gMWxsICogKHJldl9oW3JdIC0gcmV2X2hbbCAtIDFdICsgTU9EKSAlIE1PRCAqIGludl9wX3Bvd1tsIC0gMV0gJSBNT0Q7IAp9Cgpib29sIGlzUGFsaW4oaW50IGwsIGludCByKSB7CglyZXR1cm4gKGdldEhhc2gobCwgcikgPT0gZ2V0UmV2SGFzaChsLCByKSk7IAp9CgovLyBW4bubaSBt4buXaSB0w6JtIMSR4buRaSB44bupbmcgY2VudGVyIHRow6wgdMOsbSDEkeG7mSBkw6BpICJiw6FuIGvDrW5oIiBs4bubbiBuaOG6pXQKaWkgbWF4T2RkTGVuZ3RoKCkgewoJaWkgYmVzdCA9IHswLCAwfTsgIAoJZm9yIChpbnQgY2VudGVyID0gMTsgY2VudGVyIDw9IG47IGNlbnRlcisrKSB7CgkJaW50IGwgPSAwLCByID0gbWluKGNlbnRlciAtIDEsIG4gLSBjZW50ZXIpLCBhbnMgPSAwOyAKCQl3aGlsZSAobCA8PSByKSB7CgkJCWludCBtaWQgPSAobCArIHIpID4+IDE7IAoJCQlpZiAoaXNQYWxpbihjZW50ZXIgLSBtaWQsIGNlbnRlciArIG1pZCkpIHsKCQkJCWFucyA9IG1pZDsgIAoJCQkJbCA9IG1pZCArIDE7IAoJCQl9CgkJCWVsc2UgewoJCQkJciA9IG1pZCAtIDE7IAoJCQl9CgkJfQoJCW1heGltaXplKGJlc3QsIG1ha2VfcGFpcigyICogYW5zICsgMSwgY2VudGVyIC0gYW5zKSk7IAoJfQoJcmV0dXJuIGJlc3Q7IAp9CgppaSBtYXhFdmVuTGVuZ3RoKCkgewoJaWkgYmVzdCA9IHswLCAwfTsgCglmb3IgKGludCBjZW50ZXIgPSAxOyBjZW50ZXIgKyAxIDw9IG47IGNlbnRlcisrKSB7CgkJaW50IGwgPSAxLCByID0gbWluKGNlbnRlciwgbiAtIGNlbnRlciksIGFucyA9IDA7CgkJd2hpbGUgKGwgPD0gcikgewoJCQlpbnQgbWlkID0gKGwgKyByKSA+PiAxOyAgIAoJCQlpZiAoaXNQYWxpbihjZW50ZXIgLSBtaWQgKyAxLCBjZW50ZXIgKyBtaWQpKSB7CgkJCQlhbnMgPSBtaWQ7ICAKCQkJCWwgPSBtaWQgKyAxOyAKCQkJfQoJCQllbHNlIHsKCQkJCXIgPSBtaWQgLSAxOyAKCQkJfQoJCX0gCgkJbWF4aW1pemUoYmVzdCwgbWFrZV9wYWlyKDIgKiBhbnMsIGNlbnRlciAtIGFucyArIDEpKTsgCgl9CglyZXR1cm4gYmVzdDsgCn0KCmludCBtYWluKCkgewoJaW9zOjpzeW5jX3dpdGhfc3RkaW8oZmFsc2UpOyAKCWNpbi50aWUobnVsbHB0cik7IAkKCWNpbiA+PiBzOyAKCW4gPSBzLnNpemUoKTsgCglzID0gJyAnICsgczsgIAoKCXByZWNvbXB1dGUoKTsgIAoKCS8vIGFucy5maXJzdCA9IMSR4buZIGTDoGkgeMOidSBjb24gxJHhu5FpIHjhu6luZyBkw6BpIG5o4bqldAoJLy8gYW5zLnNlY29uZCA9IHbhu4sgdHLDrSBi4bqvdCDEkeG6p3UgY+G7p2EgbsOzIHRyb25nIHjDonUgcwoJaWkgYW5zID0gbWF4KG1heE9kZExlbmd0aCgpLCBtYXhFdmVuTGVuZ3RoKCkpOyAKCglzdHJpbmcgdCA9IHMuc3Vic3RyKGFucy5zZWNvbmQsIGFucy5maXJzdCk7IAoJY291dCA8PCB0IDw8ICdcbic7IAp9