leetcode 5:Longest Palindromic Substring 三种解法的java实现源代码,以及详细讲解

题目分析:查找一个字符串中中最长回文字符串

1.算法1:暴力检索

   既然要查最长的回文字符串,那么直接对每一个字符,以它为中心,找到最长的回文字符串,更新最大值最小值就行了。注意要分两种情况,1
/**对每一个字母,都查找最大的回文串的长度,left,right分别表示回文串的起始位置*/
	public String longestPalindrome(String s) {
		int start = 0, end = 0;
		int maxLen = 1;
		for (int i = 0; i < s.length(); i++) {
			int left = i;
			int right = i;
			while (left > -1 && right < s.length()
					&& s.charAt(left) == s.charAt(right)) {
				left--;
				right++;
			}
			if (maxLen < right - left + 1) {
				maxLen = right - left + 1;
				start = left + 1;
				end = right - 1;
			}
			/**字符串长度为偶数*/
			left = i;
			right = i + 1;
			while (left > -1 && right < s.length()
					&& s.charAt(left) == s.charAt(right)) {
				left--;
				right++;
			}
			if (maxLen < right - left + 1) {
				maxLen = right - left + 1;
				start = left + 1;
				end = right - 1;
			}

		}
		return s.substring(start, end + 1);
	}

2. 动态规划

感觉第一个方法代码太多,而且很多重复计算,能不能之后的结果依据之前的结果,就想到了使用动态规划,主要是长度是慢慢扩展的,可以向依据长度变化的动态规划。
/**动态规划的思路,主要是考虑其实规划的时候是从内向外的扩展,主要考虑回文串的长度*/
	public String longestPalindrome(String s) {
		int start=0;
		int end=0;
		int max=1;
		int len=s.length();
		if(len<1) return "";
		if(len==1) return s;
		char[] a=s.toCharArray();
		boolean[][] dp=new boolean[len][len];
		/**长度为1和2*/
		for(int i=0;imax)
					{
						max=l;
						start=i;
						end=j;
					}
				}
				
			}
		}
		return s.substring(start, end+1);
	}

3. manacher算法

之上的两个算法都是o(n^2).然后搜索了一下,就发现被安利的manacher算法。先解释一下算法原理吧。算法主要是依据回文字符串的对称性来减少计算。
首先,为了消除诸如第一个算法中出现的奇数,偶数的影响,我们先进行一下预处理,在每一个字母之前都加一个#,这样每一个都为中心的都是回文串都是奇数个。为了防止处理中出现越界情况,所以我们可以在字符串的开始和结束加入特殊字符,比如(^$);
其次,为了更好的利用回文字符串的对称性,我们只需要对称字符串能够到达的最远位置r,以及对称中心cen.最后我们分情况讨论
假设对称中心为i,现在需要计算i+k位置,其对应位置为(i-k),P[i]为i向右延伸的回文串的长度
(1)i+k 大于r,那么之前的计算跟现在的没关系,只能仿照方法1计算
(2)i+k小于r 但是i+k+P[i-k]
  (3)i+k小于r,i+k+P[i-k]>=r   P[i+k]=r-(i+k)
源代码如下:
public String longestPalindrome(String s) {
		String str=prepare(s);
		int n=str.length();
		int cen=0;
		int r=0;
		int[] p=new int[n];
		char[] a=str.toCharArray();
		for(int i=1;ir)
			{
				cen=i;
				r=p[i]+i;
			}
		}
		/**找到长度最大的元素*/
		  int len = 0;
		  int centerIndex = 0;
		  for (int i = 1; i < n-1; ++i){
		    if(p[i] > len){
		      len = p[i];
		      centerIndex = i;
		    }
		  }
		  return s.substring((centerIndex-len-1)/2, (centerIndex+len-1)/2);
		
	}
	public String prepare(String s)
	{
		if(s.length()==0) return "^$";
		String ret="^";
		for(char c:s.toCharArray())
		{
			ret+="#"+c;
		}
		ret+="#$";
		return ret;
	}
	



    

你可能感兴趣的:(leetcode)