资料来源网络 参见http://www.cnblogs.com/biyeymyhjob/archive/2012/10/04/2711527.html
找字符串中的最大回文子串
算法基本要点:
首先用一个非常巧妙的方式,将所有可能的奇数/偶数长度的回文子串都转换成了奇数长度:在每个字符的两边都插入一个特殊的符号。比如 abba 变成 #a#b#b#a#, aba变成 #a#b#a#。然后就可以运用manacher算法。
public class Solution {
public String longestPalindrome(String str)
{
if(str == null||str.length()<2)
return str;
//对str进行预处理操作,添加‘#’;
StringBuilder sb=new StringBuilder("#");
for(int i=0;i<str.length();i++)
{
sb.append(str.charAt(i));
sb.append('#');
}
str=sb.toString();
return manacher(str);
}
public String manacher(String str)
{
int []p=new int[str.length()];
//id代表当前最大回文子串中心的下标,mx表示当前最大回文子串所能达到最右端的距离+1(并没有达到!);
int mx=0;
int id=0;
for(int i=1;i<str.length();i++)
{
if(mx>i)
{
p[i]=p[2*id-i]<mx-i?p[2*id-i]:mx-i;
}
else
{
p[i]=1;
}
//防止下标越界;更新p[i];
while(i-p[i]>=0&&i+p[i]<str.length()&&(str.charAt(i-p[i]) == str.charAt(i+p[i])))
p[i]++;
if(i+p[i]>mx)
{
mx=i+p[i];//mx不会越界;
id=i;
}
}
//找出p[i]中最大的;
int max=0;
int index=0;
for(int j=0;j<p.length;j++)
{
if(p[j]>max)
{
index=j;
max=p[j];
}
}
//如#a#b#b#a#,
//对应的p[i]为021252121,start和end为该回文子串起始和终止的地方,
//index == 4,max == 5,可简单的观测出start和end与max和index对应关系;
max=max-1;
int start=index-max;
int end=index+max;
StringBuilder sb=new StringBuilder();
for(int k=start;k<=end;k++)
{
if(str.charAt(k)!='#')
sb.append(str.charAt(k));
}
String string =sb.toString();
//System.out.println(string);
return string;
}
}