#include <vector> #include <iostream> #include <string> using namespace std; string Manacher(string s) { // 插入特殊符号“#” string t = "$#"; for (int i = 0; i < s.size(); ++i) { t += s[i]; t += "#"; } // 初始化变量 vector<int> p(t.size(), 0); int mx = 0, id = 0, resLen = 0, resCenter = 0; //循环t.size()-1次 for (int i = 1; i < t.size(); ++i) { // p[i]:表示以 t[i] 字符为中心的回文子串的半径 // i < mx 的含义:证明 i 在 当前id 对应子回文串的范围之内 p[i] = i<mx ? min(p[2 * id - i], mx - i) : 1; //从字符串中点向两端扩展,直到不能再扩展 while (t[i + p[i]] == t[i - p[i]]){ ++p[i]; } //mx:当前已经处理的回文子串所达最靠后的终点 //id:终点最靠后的回文子串的中心字符下标 if (mx < i + p[i]) { mx = i + p[i]; id = i; } //结果 //回文字符串最大长度reslen //回文字符串的中心位置resCenter if (resLen < p[i]) { resLen = p[i]; resCenter = i; } } //例子: "noon",中间的 '#' 在字符串 "$#n#o#o#n#" 中的位置是5,半径也是5, //字符串的长度(半径减一):4,起始位置(中间位置减去半径再除以2):0 //结论:最长子串的长度是半径resLen减1,起始位置是中间位置resCenter减去半径resLen再除以2。 return s.substr((resCenter - resLen) / 2, resLen - 1); } //主程序 int main() { string s = "aawaw"; cout << Manacher(s) << endl; }
参考:
https://www.jianshu.com/p/c82cada7e5b0
https://www.cnblogs.com/grandyang/p/4475985.html
https://www.jianshu.com/p/7dacc9a3c9a0