manacher算法也称“马拉车算法”,是用来解决求字符串的最长回文串的算法。
对于求最长回文串有三种算法:
1.暴力枚举法 优点:简单易写
缺点:复杂度过高(o(n^3))
string s;
cin >> s;
int maxlength =1,start=0;
for (int i = 0; i < s.size(); i++)
{
for (int j = i + 1; j < s.size(); j++)
{
int temp1, temp2;
for (temp1 = i, temp2 = j; temp1 < temp2; temp1++, temp2--)
{
if (s[temp1] != temp2)
{
break;
}
}
if (temp1 >= temp2 && j - 1 + 1 > maxlength)
{
maxlength = j - 1 + 1;
start = i;
}
}
}
cout << s.substr(start, maxlength);
2.由中间展开,分为奇偶数两种情况
string longestPalindrome(string s)
{
if(s.empty())
{
return " ";
}
int imax=0;
int ileft=0,iright=0;
for(int i=0;i<s.size();i++)
{
if(i-1>=)
{
if(s[i]==s[i-1])
{
int ltmp=i-2,rtmpi+1;
while(ltmp>=0&&rtmp<s.size())
{
if(s[ltmp]!=s[rtmp])
{
break;
}
--ltmp;
++rtmp;
}
if(imax<rtmp-ltmp-1)
{
imax= rtmp-ltmp-1;
ileft = ltmp+1;
iright = rtmp-1;
}
}
int ltmp=i-1,rtmp=i+1
while(ltmp>=0 && rtmp<s.size())
{
if(s[ltmp] != s[rtmp])
{
break;
}
--ltmp;
++rtmp;
}
if(imax < rtmp-ltmp-1)
{
imax = rtmp-ltmp-1;
ileft = ltmp+1;
iright = rtmp-1;
}
}
}
return s.substr(ileft,iright+1-ileft);
}
优点:降低复杂度
缺点:要分奇偶性
未充分利用前面查找工作的结果
没有思考回文字符本身的特性:
3.Manacher算法
#include <iostream>
using namespace std;
int min(int a,int b)//选取两个数值之间最小值
{
if (a > b)return b;
else
{
return a;
}
}
string Manancher(string s)
{
if (s.size() < 2) //首先筛查出字符<1个的字符串
{
return s;
}
//预处理,将所有字符串变为奇数个
string t = "$";//字符串开头先增加一个特殊字符,防止越界
for (int i = 0; i < s.size(); i++)
{
t += "#";
t+=s[i];//在每一个字符之间增加一个#
}
t += "#@";//在字符串尾部增加一个特殊字符,表示结束(其实也可以不加,因为C++中string字符串尾部自动添加'/0',表示结束)
cout << t << endl;
int n = t.size();//求出新数组的长度
int* p = new int[n];//p数组,用来求每一个字符的回文串的半径
int id = 0, mx = 0;//用来检索并求p[i] 延伸到最右端位置的那个回文子串的中心点位置,mx是该回文串能延伸到的最右端的位置
int maxlength = 0;//回文串最长半径
int index = 0;// 最长回文子串的中心位置索引
for (int i = 1; i < n - 1; i++)//从有效字符开始遍历,求出p[i],并求出maxlength
{
p[i] = mx > i ? min(p[2 * id - i], mx - i) : 1;
//左右两边延伸,拓展右边界
while (t[i + p[i]] == t[i - p[i]])
{
p[i]++;
}
// 如果回文子串的右边界超过了mx,则需要更新mx和id的值
if (mx < p[i] + i)
{
mx = p[i] + i;
id = i;
}
// 如果回文子串的长度大于maxLength,则更新maxLength和index的值
if (maxlength < p[i]-1 )
{
maxlength = p[i]-1 ;
index = i;
}
}
int start = (index - maxlength) / 2;
return s.substr(start, maxlength);
}
int main()
{
string S;
cin >> S;
cout << Manancher(S);
return 0;
}
代码都上机运行通过测试,可放心食用~