复杂算法介绍[4]-Manacher算法实现

复杂算法介绍[4]-Manacher算法实现

  直接上代码:

public class Manacher {

    /**
     * 字符串的最长回文子串
     *
     *   回文串就是字符串关于中间镜面对称
     *
     *   假设字符串是
     *   fabccba
     *
     *   最长回文串就是abccba
     *
     *
     *
     */

    /**
     *
     * 暴力解
     *
     * 找到以每个字符为中间的最长回文串是多长
     *
     * fabccba
     *
     * 依次找以f为中心,a为中心,但是需要分奇数偶数,可以补长一倍长度字符串变成
     *
     * fabccba===>#f#a#b#c#c#b#a#,就不需要区分奇数偶数了,#位置的就是当最长回文是偶数时的中间位置
     *
     * 最后回文长度就是求出的长度/2
     *
     *
     *
     */




    /**
     *   解法2,也需要补长度
     *
     *   fabccba===>#f#a#b#c#c#b#a#
     *
     *   见manacher算法相关文档
     *
     *
     *
     */


    public static int manacher(String s){

        if(s == null || s.length()==0){
            return 0;
        }

        char[] str = manacherString(s);

        int[] pAry = new int[str.length];

        int C =-1;
        int R =-1; //R是第一个不匹配的位置

        int max = Integer.MIN_VALUE;


        for (int i = 0; i < str.length; i++) {

            pAry[i] = i<R? Math.min(pAry[2*C-i],R-i):1; //当i>=R,标识已经到R外部,要使用暴力扩展,但是自己肯定恨自己是回文,所以初始值是1

            while(i+pAry[i]<str.length && i-pAry[i]>-1){

                if(str[i+pAry[i]] == str[i-pAry[i]]){ //如果i<R,则这个判断会不成立,循环直接退出
                    pAry[i]++;
                }else{
                    break;
                }


            }

            //更新右边界

            if(i+pAry[i]>R){

                R = i + pAry[i];
                C = i;
            }

            max = Math.max(max,pAry[i]);

        }
        return max -1;

    }


    public  static char[] manacherString(String s){

        char[] charArr = s.toCharArray();
        char[] res = new char[2*charArr.length+1];
        int index = 0;

        for (int i = 0; i != res.length; i++) {

            res[i] = (i&1) ==0 ?'#':charArr[index++];

        }

        return res;


    }


    public static void main(String[] args) {

        String s = "fabccba";

        System.out.println(manacher(s));

    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值