回文,亦称回环,是正读反读都能一样的字符串。例如“12321”、“abba”等。
现在给你一个字符串,请你找出其中长度最长的回文。
输入描述:
输入有多组数据。
每组数据有一行,包含一个长度小于100个字符的字符串s,且仅由字母和数字构成。
如果有多个长度相等的回文,仅输出第一个。
输出描述:
对应每一组输入,输出其中长度最长的回文字符串。
/**
* 最长回文子串求解的四种方法
*/
public class GetPalindrome {
public static void main(String[] args) {
/*System.out.println(new GetPalindrome().getPalindrome("abc1234321caa"));*/
/*System.out.println(new GetPalindrome().getPalindromeByCenter("abcdaa"));*/
/*System.out.println(new GetPalindrome().getpalindromeDP("abc1234321caa"));*/
new GetPalindrome().getPalindromeManacher("abc1234321caa");
}
/**
* 暴力求解法
* 时间复杂度O(N^3)
* @param source
* @return
*/
public String getPalindrom(String source){
int len = source.length();
String str;
int start = 0;
/*
* length更新子串长度
*/
int length = 1;
int end = 1;
for(int i = 0;i<len;i++){
for(int j = i+1;j<len;j++){
str = source.substring(i,j+1);
if(isPalindrom(str)){
int size = j-i+1;
if(size>length){
length = size;
start = i;
end = j+1;
}
}
}
}
return source.substring(start,end);
}
/**
* 判断子串是否是回文子串
* @param s
* @return
*/
public boolean isPalindrom(String s){
int start = 0;
int end = s.length()-1;
while(start<end){
if(s.charAt(start)!= s.charAt(end)){
return false;
}
start++;
end--;
}
return true;
}
/**
* 中心法
* 时间复杂度O(N^2)
* @param source
* @return
*/
public String getPalindromeByCenter(String source){
int length = source.length();
int size = 1;
String str ;
String subString = "";
for(int i = 0;i<length;i++){
/*
* 以下标i位置的元素为对称中心
*/
str = palindromeByCenter(source, i, i);
if(str.length()>size){
size = str.length();
subString = str;
}
/*
* 以下标i和i+1之间的空隙为对称中心
*/
str = palindromeByCenter(source, i, i+1);
if(str.length()>size){
size = str.length();
subString = str;
}
}
return subString;
}
/**
* 中心法求最长回文子序列
* @param s
* @param i
* @param j
* @return
*/
public String palindromeByCenter(String s,int i,int j){
int len = s.length()-1;
while(i>=0&&j<=len&&s.charAt(i)==s.charAt(j)){
i--;
j++;
}
return s.substring(i+1,j);
}
/**
* 动态规划求解
* 时间复杂度O(N^2)
* @param source
* @return
* 令F[i,j] = 1 表示i到j的序列是回文序列。
* F[i,i] = 1;
* F[i,i+1]=1; S[i]=S[i+1];
* F[i+1,j-1]=1&&S[i]=S[j] => F[i,j]=1
*/
public String getpalindromeDP(String source){
int N = source.length();
int[][] dp = new int[N][N];
int size = 1;
int start = 0;
for(int i = 0;i<N;i++) {
dp[i][i] = 1;
}
for(int i = 0;i<N-1;i++){
if(source.charAt(i)==source.charAt(i+1)){
dp[i][i+1] = 1;
size = 2;
start = i;
}
}
/**
* sec 代表步长,从2到N-1
*/
for(int sec = 2;sec<=N-1;sec++){
for(int i = 0;i<N-sec;i++){
int j = i+sec;
if(source.charAt(i)==source.charAt(j)&&dp[i+1][j-1]==1){
dp[i][j] = 1;
start = i;
size = j-i+1;
}
}
}
return source.substring(start,start+size);
}
/**
* Manacher算法
* 时间复杂度O(N)
* @param s
*/
public void getPalindromeManacher(String s){
int N = s.length();
/*
* 处理原字符串
*/
StringBuilder sb = new StringBuilder();
sb.append("#");
for(int i = 0;i<N;i++){
sb.append(s.charAt(i));
sb.append("#");
}
int len = sb.length();
int[] rad = new int[len];
int center = -1;
int right = 0;
for(int i = 0;i<len;i++){
int r = 1;
/*
* 确定最小半径
*/
if(i<right){
r = Math.min(right-i,rad[2*center-i]);
}
/*
* 尝试扩展半径
*/
while(i-r>=0&&i+r<len&&sb.charAt(i-r)==sb.charAt(i+r)){
r++;
}
if(i+r>right){
center = i;
right = i+r;
}
rad[i] = r;
}
int max = 1;
int index = -1;
for(int k = 0;k<len;k++){
if(rad[k]>max){
max = rad[k];
index= k;
}
}
StringBuilder sc = new StringBuilder() ;
for(int i = index-max+1;i<=index+max-1;i++){
char c = sb.charAt(i);
if(c!='#'){
sc.append(sb.charAt(i));
}
}
System.out.println(sc.toString());
System.out.println(max-1);
}
}