Manacher解决的是最大回文子串的问题。
给定一个字符串str,返回str最长回文子串的长度。
比如:str1="123" 返回1
str2="abc1234321ab" 回文子串为“1234321”,返回7
Manacher 存在实轴虚轴对称的问题,所以要先处理生成Manacher字符串,添加的辅助字符,任意。
1221 -> #1#2#2#1#
Manacher 3个概念,4个处理分支。
3个概念:回文半径,最大右边界,中心点,求的是回文半径数组。
4个分支: 1.i在R外 暴力扩
2.I在R内 i* 在LR内 出答案
i* 在LR外 出答案
i* 左边压L 暴力扩
此算法,代码很少,但是一个while循环解决了四种情况,是我见过的最精妙的代码,没有之一。
上代码
// 输入一个字符串,返回最大回文串起始位置
int myMaxLcpsLength(string s)
{
if (s.length() == 0) { return 0; }
//1.manacherString
string str = myManacherString(s); // 12321 -> #1#2#3#2#1#
vci pArr; //1. 回文半径数组
pArr.resize(str.length());
int C = -1; // 2.中心
int R = -1; // 3.回文右边界的再往右一个位置
int m_max = 0;
for (int i = 0; i != str.length(); i++)
{
pArr[i] = R > i ? min(pArr[2 * C - i], R - i) : 1;
while (i + pArr[i] < str.length() && i - pArr[i] > -1)
{
if (str[i + pArr[i]] == str[i - pArr[i]])
pArr[i]++;
else
{
break;
}
}
if (i + pArr[i] > R)
{
R = i + pArr[i];
C = i;
}
m_max = max(m_max, pArr[i]);
}
return m_max - 1;
}
void manacher_test()
{
string str1 = "abc1234321abcde";
cout << myManacherString(str1) << endl;
cout<<myMaxLcpsLength(str1)<<endl;
}