5. 最长回文子串
【题目】:
【方法1】:中心拓展法,参考647. 回文子串
// 中心拓展法
public String longestPalindrome1(String s) {
if(s==null || s.length()<=1){
return s;
}
String res="";
for(int i=0; i<s.length(); i++){
String odd=extendSubStrings(s, i, i);
String even=extendSubStrings(s, i, i+1);
res = res.length()>odd.length()? res:odd;
res = res.length()>even.length()? res:even;
}
return res;
}
private String extendSubStrings(String s, int begin, int end ){
while(begin>=0 && end<s.length() && s.charAt(begin)==s.charAt(end)){
begin--;
end++;
}
return s.substring(begin+1, end);
}
效果:
【方法2】:马拉车算法
马拉车算法详细解析见:https://blog.csdn.net/pengchengliu/article/details/92084519,文中也提到暴力法和动态规划法
//马拉车算法
public String longestPalindrome(String s) {
if(s==null || s.length()<=1){
return s;
}
//隔一个字符插入一个#
char[] S=s.toCharArray();
int lend=s.length()*2+1;
char[] a=new char[lend];
for(int i=0; i<s.length(); i++){
a[2*i]='#';
a[2*i+1]=S[i];
}
a[lend-1]='#';
//隔一个字符插入一个#
//String str=s.replaceAll("","#"); //这种方法不如上面用数组实现快
//char[] a=str.toCharArray();
//int lend=a.length;
int[] len=new int[lend];
int c=0, right=0;
for(int i=0; i<lend; i++){
if(i >= right){
int step = 1;
while(i-step >= 0 && i+step <lend && a[i-step] == a[i+step]){
len[i]++;
step++;
}
if(i+step-1 > right){
c = i;
right = i+step-1;
}
}else if(i < right){
int j=c-(i-c);
if(len[j] < right-i){
len[i]=len[j];
}else{
int step = right+1;
len[i] = right-i;
while(i-(step-i)>=0 && step<lend && a[i-(step-i)]==a[step]){
len[i]++;
step++;
}
if(step-1 >right){
c=i;
right = step-1;
}
}
}
}
int max=0;
for(int i=0; i<lend; i++){
if(len[i]>max){
max=len[i];
c=i;
}
}
int begin=(c-len[c])/2;
return s.substring(begin, begin+len[c]);
}
效果:
对于寻找最长回文子串问题,最经典的是中心拓展和动态规划算法,马拉车算法效率最高。