部分文章内容为公开资料查询整理,原文出处可能未标注,如有侵权,请联系我,谢谢。邮箱地址:gnivor@163.com ►►►需要气球么?请点击我吧!

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

posted @ 2015-07-13 16:04  流了个火  阅读(116)  评论(0)    收藏  举报
►►►需要气球么?请点击我吧!►►►
View My Stats