Description:
Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.
Example 1:
Input: "babad" Output: "bab" Note: "aba" is also a valid answer.
Example 2:
Input: "cbbd" Output: "bb"
1,暴力法
判断字符串s的所有子串a是否为回文字符串,如果是,则返回字符串a与其长度l。最终返回长度最长的回文子串。
class Solution { public String longestPalindrome(String s) { String s1; String st = null; int maxLenrth = 0; if (s.length() == 1 || s.length() == 0) { return s; }else { for (int i = 0; i < s.length(); i++) { for (int j = i; j < s.length(); j++) { s1 = s.substring(i, j+1); if (isHw(s1)>maxLenrth) { maxLenrth = isHw(s1); st = s1; } } } return st; } }
//判断是否为回文 是返回其长度 否返回0 public int isHw(String s){ for (int i = 0; i < s.length()/2; i++) { if (s.charAt(i) != s.charAt(s.length()-i-1)) { return 0; } } return s.length(); } }
2,中心扩展法
中心扩展就是把给定的字符串的每一个字母当做中心,向两边扩展,这样来找最长的子回文串。算法复杂度为O(N^2)。
需要考虑两种情况:
长度为奇数的回文串,比如a, aba, abcba
长度为偶数的回文串,比如aa, abba
//最长回文子串 -- 中心扩展法 public static String longestHWStrings(String s){ int len = s.length(); int maxlen = 1; int start = 0; //长度为奇数的回文串 for (int i = 0; i < len; i++) { int j = i-1,k = i+1; while(j>=0 && k<len && s.charAt(j)==s.charAt(k)){ if(k-j+1 > maxlen){ maxlen = k-j+1; start = j; } j--; k++; } } //长度为偶数的回文串 for (int i = 0; i < len; i++) { int j = i,k = i+1; while(j>=0 && k<len && s.charAt(j)==s.charAt(k)){ if(k-j+1 > maxlen){ maxlen = k-j+1; start = j; } j--; k++; } } return s.substring(start,start+maxlen); }
3,动态规划
使用动态规划的策略解决该问题。首先,从子问题出发,并将子问题的解保存起来,然后在求解后面问题时,反复利用子问题的解,可以极大的提高效率。
由于最长回文子串是要求连续的,所以我们可以假设 j
为子串的起始坐标,i
为子串的终点坐标,其中 i
和 j
都是大于等于 0
并且小于字符串长度 len
的,且 j <= i
,这样子串的长度就可以使用 i - j + 1
表示了。
我们从长度为 1 的子串依次遍历,长度为 1 的子串肯定是回文的,其长度就是 1;然后是长度为 2 的子串依次遍历,只要 str[i]
等于 str[j]
,它就是回文的,其长度为 2;接下来就好办了,长度大于 2 的子串,如果它要满足是回文子串的性质,就必须有 str[i]
等于 str[j]
,并且去掉两头的子串 str[j+1 ... i-1]
也一定是回文子串,所以我们使用一个数组来保存以 j
为子串起始坐标,i
为子串终点坐标的子串是否是回文的,由于我们是从子问题依次增大求解的,所以求解 [i ... j]
的问题时,比它规模更小的问题结果都是可以直接使用的了。 引用
状态方程和转移方程:
- P[i, j] = P[i+1, j-1], if ( s[i]==s[j] )
- P[i, j] = false,if ( s[i] != s[j] )
//LPS -- 最长回文子串 动态规划 public static String getLPS(String s){ if(s.equals("")){ return ""; } char[] c = s.toCharArray(); int len = c.length; //第一维参数表示起始坐标 第二维参数表示终点坐标 //lps[j][i]表示以j为起始坐标i为终点坐标的字符串是否为回文字符串 boolean lps[][] = new boolean[len][len]; int maxlen = 1; int start = 0; for (int i = 0; i < len; i++) { for (int j = 0; j <= i; j++) { if(i-j<2){ lps[j][i] = c[j]==c[i]; }else{ lps[j][i] = lps[j+1][i-1] && (c[j]==c[i]); } if(lps[j][i] && (i-j+1)>maxlen){ maxlen = i-j+1; start = j; } } } return s.substring(start,start+maxlen); }