5. Longest Palindromic Substring
更新:
之前那种dp太笨重了有个非常的轻巧的做法,原理都是一样的。
转移方程不变,但是不需要特别的初始化
判断某个格子是不是true,是
1.要么长度小于3,要么dp[start+1][end-1]==true
2.并且s.charAt(start) == s.charAt(end)
判断要不要更新resultStr:
在dp[start][end] == true的情况下
1.要么resultStr.length() == 0,就是一次都没有赋值过
2.要么resultStr.length() < end - start + 1
更新resultStr
1 public String longestPalindrome(String s) { 2 String res = ""; 3 if(s == null || s.length() == 0) { 4 return res; 5 } 6 int len = s.length(); 7 boolean[][] dp = new boolean[len][len]; 8 for(int l = 0; l < len; l++) { 9 for(int start = 0; start < len - l; start++) { 10 int end = start + l; 11 dp[start][end] = end - start < 2 || (dp[start + 1][end - 1] && s.charAt(start) == s.charAt(end)); 12 if(dp[start][end] && res.length() < end - start + 1) { 13 res = s.substring(start, end + 1); 14 } 15 } 16 } 17 return res; 18 }
________________________________________________________________
方法一:动态规划
基本公式:
matrix[i][j] = true, if matrix[i+1][j-1] == true && str[i] == str[j]
matrix[i][j] = false, otherwise
初始化,需要把长度为1和2的串先标好true/false
思路:
1. 初始化:
1)标记所有长度为1的子串为真:对于所有matrix[i][i]=true
2) 标记所有长度为2的子串的真假:对于所有matrix[i][i+1] = str[i] == str[i+1]
2.填写matrix:
对于长度len从2到strLen:
对于位置i从0到strLen-len:
如果 matrix[i+1][j-1] == true && str[i] == str[j],那么
matrix[i][j]=true
否则
matrix[i][j] = false
3. 寻找最大长度回文子串:
对于i从0到len:
对于j从i到len:
如果matrix[i][j] == true:
如果j-i大于maxLen:
记录maxLen
记录目前最大回文子串
4.返回全局最大回文子串
1 public String longestPalindrome(String s) { 2 if(s == null || s.length() == 0) { 3 return null; 4 } 5 int len = s.length(); 6 if(len == 1) { 7 return s; 8 } 9 boolean[][] matrix = new boolean[len][len]; 10 for(int i = 0; i < len; i++) { 11 matrix[i][i] = true; 12 } 13 for(int i = 0; i < len - 1; i++) { 14 matrix[i][i+1] = s.charAt(i) == s.charAt(i+1); 15 } 16 for(int l = 2; l < len; l++) { 17 for(int i = 0; i < len - l; i++) { 18 if(matrix[i+1][i+l-1] == true && s.charAt(i) == s.charAt(i+l)) { 19 matrix[i][i+l] = true; 20 } else { 21 matrix[i][i+l] = false; 22 } 23 } 24 } 25 int maxLen = 0; 26 String res = ""; 27 for(int i = 0; i < len; i++) { 28 for(int j = i; j < len; j++) { 29 if(matrix[i][j] == true) { 30 if(maxLen < j - i) { 31 maxLen = j - i; 32 res = s.substring(i, j+1); 33 } 34 } 35 } 36 } 37 return res; 38 }
注意事项:
string.substring(i,j)是包括第i个,但是不包括第j个
方法二:暴力解决
对于字符串里面的每一位/每一位+后一位当做中心,来对回文字符串进行拓展,直到找到最长的
1 private int startPos = 0; 2 private int maxLen = 0; 3 public String longestPalindrome(String s) { 4 if(s == null) { 5 return null; 6 } 7 int length = s.length(); 8 if(length < 2) { 9 return s; 10 } 11 for(int i = 0; i < length - 1; i++) { 12 extend(s, i, i); 13 extend(s, i, i+1); 14 } 15 System.out.println(startPos+ ";;" + maxLen); 16 return s.substring(startPos, startPos + maxLen); 17 } 18 19 private void extend(String s, int left, int right) { 20 while(left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) { 21 left--; 22 right++; 23 } 24 if(maxLen < right - left - 1) { 25 maxLen = right - left - 1; 26 startPos = left + 1; 27 } 28 }
bug记录:
20行处,最后执行是多执行了一次,所以后面24行处,要往内移动一格