算法学习 Manacher求最大回文串

为解决奇偶数回文,在字符串间添加任意辅助字符

abc->#a#b#c#

维护r和c,pArr[]  r为回文最右边界,c是当前r的回文中心点,pArr[i]是i为中心时的回文半径

1)i不在r边界内,i>r
以i为中心点暴力扩,若扩后边界大于r,更新r,c
2)i在r边界内,存在L i' c i R 。LR,ii'关于c对称
        再根据i'的回文状况划分
        1)i‘回文在LR之间 i与i’的回文情况一致(对称)
        2)i‘回文在LR之外 i的回文半径是i到R。LR之外必不相等。
        3)i’回文正好压线LR i的回文半径至少是i到R,需要在该半径基础上继续扩。

共4情况,只有1,4会使得R变化

public static int maxLcp(String s){
        if(s==null||s.length()==0){
            return 0;
        }
        char[]str=manacherString(s);//abc->#a#b#c#
        int[]pArr=new int[str.length];//回文半径数组
        int C=-1;//回文中心
        int R=-1;//回文右边界再右一个位置,R-1是有效区域,用于优化
        int max=Integer.MIN_VALUE;
        for(int i=0;i!=str.length;i++){
            //不用验的区域
            //R>i i在边界内or上,2*C-i是i‘的位置,R-i是i到右边界的位置
            //i在R外时,该字符本身不用验,为1
            pArr[i]=R>i? Math.min(pArr[2*C-i],R-i):1;
            //上一步统一把不用验证的区域跳过,while中统一扩,
            // 其中不需要扩的扩一步就会break,为了代码简洁
            
            while(i+pArr[i]<str.length&&i-pArr[i]>-1){
                if(str[i+pArr[i]]==str[i-pArr[i]]){
                    pArr[i]++;
                }else{
                    break;
                }
            }
            if(i+pArr[i]>R){
                R=i+pArr[i];
                C=i;
            }
            max=Math.max(max,pArr[i]);
        }
        //原串回文最大长度与回文半径存在以下关系
        return max-1;
    }

重点理解pArr[]的计算过程,Manacher算法的关键。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值