classSolution { public: string longestPalindrome(string s){ string manacher = "^#"; for (auto& c : s) { manacher.push_back(c); manacher.push_back('#'); } manacher.push_back('$'); // the mapping between manacher and the original string: // a, b // 0, 1 // => // ^, #, a, #, b, #, $ // 0, 1, 2, 3, 4, 5, 6 // s[i] = t[(i + 1) * 2] // t[i] = s[i / 2 - 1] vector<int> halfLen(manacher.size() - 2, 0); int center = 0, right = 0, max_idx = 0; for (int i = 2; i < halfLen.size(); i++) { int len = 1; if (i < right) { len = min(right - i, halfLen[2 * center - i]); } while (manacher[i + len] == manacher[i - len]) { if (i + len > right) { right = i + len; center = i; } len++; } halfLen[i] = len; if (len > halfLen[max_idx]) { max_idx = i; } } int hl = halfLen[max_idx]; // in fact we should use hl - 2, because manacher[i + len] != manacher[i - len] and the boundary is '#' // so the range in manacher is [max_idx - hl + 2, max_idx + hl - 2] // the range in origin is [(max_idx - hl) / 2, (max_idx + hl) / 2 - 2]; return s.substr((max_idx - hl) / 2, hl - 1); } };