java 最长回文字串

 
package string.string1_6;

public class LongestPalidrome
{
    /**
     * 使用常规方法, 以字符串的每一个字符作为中心进行判断, 包括奇数和偶数的情况
     * 最坏时间复杂度为O(N^2) , 空间复杂度O(1)
     */
    public static int longestPalidrome(String s)
    {
        if(s == null || s.length() <= 0)
            return 0 ;

        int max = 0 ;

        for(int i=0 ; i<s.length() ; i++)
        {
            for(int time=0 ; time<2 ; time++)
            {
                int length = getMax(s , i , time+i) ;
                if(max < length)
                    max = length ;
            }
        }

        return max ;
    }

    private static int getMax(String s, int left , int right) {
        while (left >= 0 && right <= s.length() - 1) {
            if (s.charAt(left) != s.charAt(right))
                break;
            left--;
            right++;
        }

        return right - left - 1;
    }

    /**
     * 使用manacher算法(其实就是动态规划的一种情况)
     * 时间复杂度O(N), 空间复杂度O(N)
     */
    public static int longestPalidrome2(String s)
    {
        if(s == null || s.length() < 1)
            return 0 ;
        String judge = init(s) ;

        int id = 0 ;    //最大回文的中心
        int mx = 0 ;    //为id+p[id], 也就是最大回文的后半段
        int[] p = new int[judge.length()] ;

        for(int i=1 ; i<judge.length()-1 ; i++)
        {
            if(i < mx)
            {
                p[i] = min(p[2*id-i] , mx-i) ;  //对p[i]进行预测
            }
            else
            {
                p[i] = 1 ; //无法使用之前的结论进行预测, 因此只能先假设p[i]只为该元素本身的长度1.
            }

            while (judge.charAt(i-p[i]) == judge.charAt(i+p[i]))    //在mx外是否仍存在回文
                p[i]++ ;

            //更新mx和id
            if(p[i]+i-1 > mx)
            {
                mx = p[i] + i -1;
                id = i ;
            }
        }

        int mxId = 0 ;
        for(int i=1 ; i<p.length ; i++)
        {
            if(p[i] > p[mxId])
                mxId = i ;
        }

        return p[mxId]-1 ;
    }

    /**
     * 预处理:将原来的字符串str填充为为$#...#*的格式
     * 由于java没有\0作为字符串的结束标志, 因此在结尾使用*作为结束标志
     * 其中的$和*是用来当哨兵的
     */
    private static String init(String str)
    {
        StringBuilder sb = new StringBuilder(str.length()*2+2) ;

        sb.append("$#") ;
        for(int i=0 ; i<str.length() ; i++)
        {
            sb.append(str.charAt(i)).append("#") ;
        }

        sb.append("*") ;
        return sb.toString() ;
    }
    private static int min(int a , int b)
    {
        return a > b ? b : a ;
    }

    public static void main(String[] args)
    {
        //dsjfkldsababasdlkfjsd
        //skjflkdsjfkldsababasdlkfjsdwieowowwpw
        String str = "a";

        System.out.println(longestPalidrome2(str));
    }
}

 

参考://https://yq.aliyun.com/articles/3739

posted @ 2016-07-03 10:06  iamzhoug37  阅读(376)  评论(0编辑  收藏  举报