本算法用于求解一个字符串中最长的回文子串,例如AbDCaCDbe的最长回文子串是bDCaCDb。
该代码求最长回文子串的长度:
import java.util.Scanner;
public class Manacher {//最长回文子串
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
while(sc.hasNext()){
String s=sc.nextLine();
if(s==null || s.length()<1) {
System.out.println(0);
return;
}
//考虑到字符串长度可能是奇数也可能是偶数,这里进行预处理,处理过后长度为奇数
StringBuilder sb=new StringBuilder("#");
for(int i=0; i<s.length(); i++){
sb.append(s.charAt(i));
sb.append('#');
}
System.out.println(manacher(sb.toString()));
}
}
public static int manacher(String s){
int maxLen=0;//记录最长的回文子串的长度
int p=0;//当前回文串的中心
int maxRig=0;//当前回文串的右边界
int[] len=new int[s.length()];//记录以每个点为中心的回文串的长度
for(int i=0; i<s.length(); i++){
if(i<maxRig) len[i]=Math.min(len[2*p-i], maxRig-i);//manacher算法的核心
else len[i]=1;
while(i-len[i]>=0 && i+len[i]<s.length() &&
s.charAt(i-len[i])==s.charAt(i+len[i])){
len[i]++;
}
if(i+len[i]>maxRig){
maxRig=i+len[i];
p=i;
}
if(len[i]>maxLen) maxLen=len[i];
}
return maxLen-1;
}
}
下面即可以求长度,也可以求子串:
public class Solution {
public String longestPalindrome(String s) {
if(s==null || s.length()<2) return s;
//考虑到字符串长度可能是奇数也可能是偶数,这里进行预处理,处理过后长度为奇数
StringBuilder sb=new StringBuilder("#");
for(int i=0; i<s.length(); i++){
sb.append(s.charAt(i));
sb.append('#');
}
s=sb.toString();
int maxLen=0;//记录最长的回文子串的长度
int p=0;//当前回文串的中心
int maxRig=0;//当前回文串的右边界
int mp=0;//最长回文串的中心
int[] len=new int[s.length()];//记录以每个点为中心的回文串的长度
for(int i=0; i<s.length(); i++){
if(i<maxRig) len[i]=Math.min(len[2*p-i], maxRig-i);//manacher算法的核心
else len[i]=1;
while(i-len[i]>=0 && i+len[i]<s.length() &&
s.charAt(i-len[i])==s.charAt(i+len[i])){
len[i]++;
}
if(i+len[i]>maxRig){
maxRig=i+len[i];
p=i;
}
if(len[i]>maxLen) {
maxLen=len[i];
mp=p;
}
}
maxLen=2*(maxLen-1)+1;
return s.substring(mp-maxLen/2, mp+maxLen/2).replaceAll("#", "");
}
}