点击打开题目

这题二刷的时候又忘了怎么做了,实在是不应该,以后还得用博客记一下。
常规做法就是以每个字母为中心,向两个方向搜索结果,时间复杂度为
。而Manacher(马拉车?)算法是一个高效且巧妙的
算法。
因为是回文串,所以串的对称位置上的字符可以共用一些信息。
例如:abaeaba是以e为中心的回文串,可以看到左边的b最长的回文串长度为3(aba),那么右边的长度也就至少为3(这一点要注意,是至少为3,但有可能更长,假如字符串的最后再加个e就更长了)。
babad -> ^#b#a#b#a#d#$
其中插入的符号可以自己改变。
/*
* @lc app=leetcode.cn id=5 lang=cpp
*
* [5] 最长回文子串
*/
class Solution {
public:
string longestPalindrome(string s) {
string str = processString(s);
int ans=0; // 结果串的长度
int ans_pos=0; // 结果串的中心
int id=0; // 搜索最远回文串的中心
int mx=0;
vector<int> p(str.size(), 0);
for (int i=1; i<str.size()-1; i++)
{
// 如果前面已经扫描到过这个位置,可以直接和对称位置比较
p[i] = mx > i ? min(p[2*id-i], mx-i) : 1;
// 不管用不用搜索,都试一下,和用if判断效果一样
while (str[i+p[i]] == str[i-p[i]])
p[i]++;
// 更新一下扫描的最远位置
if (i+p[i] > mx)
{
mx = i+p[i];
id = i;
}
// 更新结果
if (p[i] > ans)
{
ans = p[i];
// 中心位置
ans_pos = i;
}
}
return s.substr((ans_pos-ans)/2, ans-1);
}
string processString(const string &s)
{
string str = "^#";
for(int i=0; i<s.size(); i++)
{
str += s[i];
str += "#";
}
str += "$";
return str;
}
};