#include <iostream>
using namespace std;
pair<int, int> manacher(string s) {
// assuming string is in the format of #s[1]#s[2]#...#s[n]#
// format with length larger than 3 (original unpadded string
// has more than one char).
// preparation phase
int* p = new int[s.size()]();
p[0] = 1; p[1] = 2;
int mx = 3; // mx: store the index immediate after current
//longest palindrome
int ind = 1; // ind: store current longest palindrome
//center index.
for (int i = 2; i < s.size(); i++) {
// step1: precalculate p[i]
if (i < mx) {
int mirrorPi = p[2 * ind - i];
int safePi = mx - i;
p[i] = mirrorPi < safePi ? mirrorPi : safePi;
}
else {
p[i] = 1;
}
// step2: expand
while (i + p[i] < s.size() \
&& i - p[i] >= 0 \
&& s[i + p[i]] == s[i - p[i]])
p[i]++;
// step3: update mx and ind
if (i + p[i] > mx) {
mx = i + p[i];
ind = i;
}
}
return make_pair(p[ind], ind);
}
int main() {
string s = "#1#2#2#1#2#3#2#1#";
pair<int, int> p = manacher(s);
cout << "radius is " << p.first << ", center at " << p.second << endl;
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgp1c2luZyBuYW1lc3BhY2Ugc3RkOwoKcGFpcjxpbnQsIGludD4gbWFuYWNoZXIoc3RyaW5nIHMpIHsKCS8vIGFzc3VtaW5nIHN0cmluZyBpcyBpbiB0aGUgZm9ybWF0IG9mICNzWzFdI3NbMl0jLi4uI3Nbbl0jIAoJLy8gZm9ybWF0IHdpdGggbGVuZ3RoIGxhcmdlciB0aGFuIDMgKG9yaWdpbmFsIHVucGFkZGVkIHN0cmluZwoJLy8gaGFzIG1vcmUgdGhhbiBvbmUgY2hhcikuCgoJLy8gcHJlcGFyYXRpb24gcGhhc2UKCWludCogcCA9IG5ldyBpbnRbcy5zaXplKCldKCk7CglwWzBdID0gMTsgcFsxXSA9IDI7CglpbnQgbXggPSAzOwkvLyBteDogc3RvcmUgdGhlIGluZGV4IGltbWVkaWF0ZSBhZnRlciBjdXJyZW50CgkgICAgICAgICAgICAvL2xvbmdlc3QgcGFsaW5kcm9tZQoJaW50IGluZCA9IDE7IC8vIGluZDogc3RvcmUgY3VycmVudCBsb25nZXN0IHBhbGluZHJvbWUKCSAgICAgICAgICAgICAvL2NlbnRlciBpbmRleC4KCglmb3IgKGludCBpID0gMjsgaSA8IHMuc2l6ZSgpOyBpKyspIHsKCQkvLyBzdGVwMTogcHJlY2FsY3VsYXRlIHBbaV0KCQlpZiAoaSA8IG14KSB7CgkJCWludCBtaXJyb3JQaSA9IHBbMiAqIGluZCAtIGldOwoJCQlpbnQgc2FmZVBpID0gbXggLSBpOwoJCQlwW2ldID0gbWlycm9yUGkgPCBzYWZlUGkgPyBtaXJyb3JQaSA6IHNhZmVQaTsKCQl9CgkJZWxzZSB7CgkJCXBbaV0gPSAxOwoJCX0KCgkJLy8gc3RlcDI6IGV4cGFuZAoJCXdoaWxlIChpICsgcFtpXSA8IHMuc2l6ZSgpIFwKCQkJICAgJiYgaSAtIHBbaV0gPj0gMCBcCgkJCSAgICYmIHNbaSArIHBbaV1dID09IHNbaSAtIHBbaV1dKQoJCQlwW2ldKys7CgoJCS8vIHN0ZXAzOiB1cGRhdGUgbXggYW5kIGluZAoJCWlmIChpICsgcFtpXSA+IG14KSB7CgkJCW14ID0gaSArIHBbaV07CgkJCWluZCA9IGk7CgkJfQoJfQoKCXJldHVybiBtYWtlX3BhaXIocFtpbmRdLCBpbmQpOwp9CgoKaW50IG1haW4oKSB7CglzdHJpbmcgcyA9ICIjMSMyIzIjMSMyIzMjMiMxIyI7CgoJcGFpcjxpbnQsIGludD4gcCA9IG1hbmFjaGVyKHMpOwoJY291dCA8PCAicmFkaXVzIGlzICIgPDwgcC5maXJzdCA8PCAiLCBjZW50ZXIgYXQgIiA8PCBwLnNlY29uZCA8PCBlbmRsOwoKIAlyZXR1cm4gMDsKfQ==