LeetCode--5. Longest Palindromic Substring
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.
给出一个字符串s,寻找最长的回文子串
例如s="121232111"最长回文为12321
s="56512332177"最长回文为123321
解法1:遍历每个字符,以此字符为中心,向两侧扩展,时间复杂度O(n^2)
注意:需要分别考虑回文为奇数和回文为偶数的情况。
public static void main(String[] args) { //String str = longestPalindrome("ababcbaaaaa"); String str = longestPalindrome("ababccbaaaaeceaa"); System.out.println("最长公共子串为" + str); } public static String longestPalindrome(String s) { int len = s.length(); //回文是单数的情况,求出最长回文 int maxmid = 0; //中间位置 int max = 0; //数量的一半+1 例如 回文长为7 那么max是4 //单数的情况 for (int mid = 0; mid < len; mid++) { for (int i = mid, j = mid; i >= 0 && j < len; i--, j++) { if (s.charAt(i) == s.charAt(j)) { if (max < j - mid + 1) { max = j -mid+1; maxmid = mid; } } else break; } } //回文是双数的情况,求出最长回文 int maxmid2 = 0; //中心位置(偏左侧的那个,例如 abccba,那么maxmid2指示第一个c) int max2 = 0; // 长度/2+1 for (int mid2 = 0; mid2 < len; mid2++) { for (int i = mid2, j = mid2+1; i >= 0 && j < len; i--, j++) { if (s.charAt(i) == s.charAt(j)) { if (max2 < j - mid2 + 1) { max2 = j -mid2+1; maxmid2 = mid2; } } else break; } } if(max2>max){ System.out.println("maxmid2:"+maxmid2+" max2:"+max2); return (String) s.subSequence(maxmid2-max2+2, maxmid2+max2); }else{ System.out.println("maxmid:"+maxmid+" max:"+max); return (String) s.subSequence(maxmid-max+1, maxmid+max); } }
解法2:动态规划
设置一个数组二维数组isPalindrome[][],数组元素isPalindrome[i][j]=true 表示从i到j的子串为回文。
比较过程:按照对角线的方向进行。
例如:判断s[1,2,3,4,5]是不是回文,首先获取数组isPalindrome[2][4],如果为true,且s[1]==s[5]那么就是回文。更新isPalindrome[1][5]=true.
而isPalindrome[2][4]在isPalindrome[1][5]的左下方,已经求到了,可以直接用。然后将行列坐标分别+1,对下一个元素进行处理。
public static void main(String[] args) { //String str = longestPalindrome("bb"); String str = longestPalindrome("ababccbaaaaeceaa"); //String str = longestPalindrome("abcba"); System.out.println("最长公共子串为" + str); } public static String longestPalindrome(String s) { int len = s.length(); //isPalindrome[i][j]=true 表示从i到j的子串为回文 boolean[][] isPalindrome = new boolean[len][len]; for(int i = 0 ; i < len ; i++){ isPalindrome[i][i] =true; //单个元素为回文 } for(int i = 0 ; i < len-1 ; i++){ isPalindrome[i+1][i] =true; //将对角线下一行也设置为true,方便下面只有两个元素的时候进行比较的情况 } int maxlen = 1; int maxi = 0 ; int maxj = 0; for(int i = 1 ; i < len ; i++){ for(int n = 0 ; n<len-i ;n++){ //这里的i为最长回文长度-1 if(isPalindrome[n+1][i+n-1]==true&&s.charAt(n)==s.charAt(i+n)){ isPalindrome[n][i+n]=true; if(maxlen<=i){ //更新最长长度 maxlen = i+1; maxi=n; maxj=i+n; } } else isPalindrome[n][i+n]=false; } } for(int i = 0 ; i < len ; i++){ //输出结果数组 for(int j = 0 ;j < len ;j ++) System.out.print(isPalindrome[i][j]+"\t"); System.out.println(); } return (String)s.substring(maxi,maxj+1); }
解法3:manacher算法,详细见另一篇博文
http://www.cnblogs.com/gnivor/articles/4644827.html

浙公网安备 33010602011771号