leetCode—Longest Palindromic Substring

Description:Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring.

问题描述:给出一个字符串,求出这个字符串的最大回文子字符串。

解法一:看到这个问题,我们首先很容易想出时间复杂度是O(n^2),空间复杂度为O(n^2)的动态规划方法


代码如下:

public String longestPalindrome(String s) {
        if(s==null||s.length()==0)
			return null;
		int n=s.length();
		int longestBegin=0;
		int maxLen=1;
		boolean[][] table=new boolean[n][n];
		
		for(int i=0;i<n;i++){
			table[i][i]=true;
		}
		
		for(int i=0;i<n-1;i++){
			if(s.charAt(i)==s.charAt(i+1)){
				table[i][i+1]=true;
				longestBegin =i;
				maxLen=2;
			}
		}
		
		
		for(int i=n-3;i>=0;i--){
			for(int j=i+1;j<n;j++){
				if(s.charAt(i)==s.charAt(j)&&table[i+1][j-1]){
					table[i][j]=true;
					if(maxLen<j-i+1){
						longestBegin=i;
						maxLen=j-i+1;
					}
				}
			}
		}
		
		
		return s.substring(longestBegin,longestBegin+maxLen);
    }

 
解法二: 

那么,是不是有时间复杂度和空间复杂度的都是线性的解决方法了,答案是肯定的,那就是使用Manacher’s Algorithm,(我翻译为马努切尔算法)。算法的思想可以查看这篇博客(Manacher's ALGORITHM)和Longest Palindromic Substring Part II,这个算法我从阅读思想到实现,我花了半天的时间,一开始根本看不懂,准备放弃,最后坚持看下去了,当自己写的代码通过的时候,心里还是很开心的。废话不多说了,直接给出我写的代码:

public static  String longestPalindrome(String s) {
	if(s==null||s.length()==0)
		return null;
	
	int[] arr=getP(s);
	int max=arr[0];
	int center=0;
	for(int i=1;i<arr.length;i++){
		if(arr[i]>max){
			max=arr[i];
			center=i;
		}
	}
	String res=null;
	int centerIndex=0;
	//这里面需要考虑这两种情况
	if(center%2==0){
		centerIndex=(center-2)/2;
		res=s.substring(centerIndex-(max-2)/2,centerIndex+(max-2)/2+1);
	}
	else{
		centerIndex=(center-1)/2;
			
		res=s.substring(centerIndex-(max-1)/2, centerIndex+(max-1)/2);
	}
	return res;
		
}
	
/**
* S $#1#2#2#1#2#3#2#1#^
* P 0121252141216121210
*这个函数就是求这里面的P数组
*(p.s. 可以看出,P[i]-1正好是原字符串中回文串的总长度)
* */
public static int[] getP(String s){
	String str=preprocess(s);
	int[] p=new int[str.length()];
	int mx=0;
	int id=0;
	for(int i=1;i<str.length()-1;i++){
		if(mx>i){
			p[i]=Math.min(p[2*id-i], mx-i);
		}
		else
			p[i]=1;
			
		while(str.charAt(i+p[i])==str.charAt(i-p[i]))
		{	p[i]++;
				
		}
			
		if(i+p[i]>mx){
			mx=i+p[i];
			id=i;
		}
	}
		
	return p;
}
	
/**
 *处理字符串,把字符串形如“12212321”转化成“$#1#2#2#1#2#3#2#1#^” 
 *(1)在头尾加$和^字符串可以使我们不用考虑越界问题
 *(2)在中间加#字符串是为了使字符串的长度为奇数,这样就不用分奇偶两种
 *情况去考虑了,处理起来更加方便
**/

private static String preprocess(String str){
	int length=str.length();
	char[] ch=new char[2*length+3];
	ch[0]='$';
	for(int i=0;i<str.length();i++){
		ch[2*i+1]='#';
		ch[2*i+2]=str.charAt(i);
	}
	ch[2*length+1]='#';
	ch[2*length+2]='^';
		
		
	return String.valueOf(ch);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值