问题:求一个字符串中的最长回文子串 (java实现)
比如字符串google, 它的最长回文子串是goog
思路: 网上有时间复杂度是o(n)的解法,我的思路是是否可以利用以前学到的最长公共子串的解法,因为对于一个含有回文子串的字符串,其颠倒后的字符串必然也含有相同的回文子串,想到这一点,这个问题就变成了求一个字符串和其颠倒后的字符串的最长公共子串的问题了, 举个栗子, 对于googleaabaa, 其颠倒后的结果是aabaalegoog, 则这两个字符串的最长公共子串aabaa就是所要找的最长回文子串
对于最长公共子串这一典型的动态规划问题,关键是要找到并理解其状态转移方程f(i,j), f(i,j)代表了对于字符串a的第i个元素和字符串b的第j个元素,其最长公共子串的最大长度
当a[i]==b[j]时, f(i,j) = f(i-1,j-1) + 1 => 当a[i]与b[j]匹配时,f(i,j)取其左上方的值并加一
当a[i]!=b[j]时,f(i,j) = max(f(i,j-1), f(i-1,j)) => 当a[i]与b[j]不匹配时, f(i,j)的值取其左侧节点和上方节点中最大的那个
1 package com.rui.microsoft; 2 3 public class Test73_LongestPalindrome { 4 5 public static void main(String[] args) { 6 Test73_LongestPalindrome app = new Test73_LongestPalindrome(); 7 String input = "googleaabaa"; 8 StringBuilder sb = new StringBuilder(input); 9 app.longestPalindrome(input.toCharArray(), sb.reverse().toString().toCharArray()); 10 } 11 12 //利用最长公共子串的解法 13 void longestPalindrome(char[] a, char[] b){ 14 int[][] score = new int[a.length+1][]; 15 char[][] direction = new char[a.length+1][]; 16 for(int i = 0; i <=a.length;i++){ 17 score[i] = new int[b.length + 1]; 18 } 19 for(int i = 0; i <=a.length;i++){ 20 direction[i] = new char[b.length + 1]; 21 } 22 23 //initialize 24 for(int i = 0; i <=a.length;i++){ 25 score[i][0] = 0; 26 } 27 for(int i = 0; i <=b.length;i++){ 28 score[0][i] = 0; 29 } 30 31 //start to mark 32 for(int i = 1; i <= a.length; i++){ 33 for(int j = 1; j <= b.length; j++){ 34 if(a[i-1] == b[j-1]){ 35 score[i][j] = score[i-1][j-1] + 1; 36 direction[i][j] = '//'; 37 }else{ 38 //go from top 39 if(score[i-1][j] > score[i][j-1]){ 40 score[i][j] = score[i-1][j]; 41 direction[i][j] = '|'; 42 }else{ 43 //go from left 44 score[i][j] = score[i][j-1]; 45 direction[i][j] = '-'; 46 } 47 } 48 } 49 } 50 51 log(score); 52 log(direction); 53 showTrace(score,direction,a,b); 54 } 55 56 void showTrace(int[][] score, char[][] direction, char[] a, char[] b){ 57 int i = a.length, j = b.length; 58 while(i > 0 && j >0){ 59 if(direction[i][j] == '//'){ 60 System.out.println(a[i-1]); 61 i--; 62 j--; 63 }else if(direction[i][j] == '-'){ 64 j--; 65 }else if(direction[i][j] == '|'){ 66 i--; 67 } 68 } 69 } 70 71 private void log(int[][] a){ 72 for(int i = 0; i < a.length; i++){ 73 for(int j = 0; j < a[i].length; j++){ 74 System.out.print(" " + a[i][j]); 75 } 76 System.out.println(" "); 77 } 78 System.out.println(" "); 79 } 80 81 private void log(char[][] a){ 82 for(int i = 0; i < a.length; i++){ 83 for(int j = 0; j < a[i].length; j++){ 84 System.out.print(" " + a[i][j]); 85 } 86 System.out.println(" "); 87 } 88 System.out.println(" "); 89 } 90 }