manacher算法代码以及基本原理

package manacher;
/*
* manacher的核心是回文半径数组,回文字符串的顺序逆序是一样的,字符是对称的,确定好的会问半径长度就可以帮助用来判断后面的i位置的回文半径,
* 首先是对字符串重新构造加上一个新字符,这个字符没有限制
* 使用字符填充后的数组构造出一个存储每个字符回文半径的数组
*构造会问半径数组rl时要注意愤青四种情况,以及每种情况的处理方式
*
*
* */
public class manacher {
    public static char[] geneManaArr(String s){
        char[] sb = s.toCharArray();
        char[] str=new  char[sb.length*2+1];
        int index=0;
        for(int i=0;i<str.length;i++){
//            if((i&1)==0){
//                str[i]='#';
//            }else{
//                str[i]=sb[index++];
//            }
            str[i]=((i&1)==0)?'#':sb[index++];
        }
         return str;
    }
    public static  int[] manach(String string){
        char[] geeArr = geneManaArr(string);
        int c=-1;//最新的中心位置
        int r=-1;//当前最新扩充的右边界,c r每次扩充玩结束更新
        int[] rl=new int[geeArr.length];
        for(int i=0;i<geeArr.length;i++){
            //在i<R给当前位置的字符一个至少不用判断的回文串长度,i>=R赋值为1并自己扩张
            //Math.min(r-i,rl[2*c-i]就是三种情况,i'的半径在L-R内部(r-i),外部以及压线L时(rl[2*c-i])对应的回文半径。区别在于压线时要进行进一步扩张判断。
            //抓住回文串对称位置想等这一点,根据对称的i’半径,判断i的回文半径
         rl[i]= i<r?Math.min(r-i,rl[2*c-i]):1;

         //扩张策略在i>R以及压线时进一步判断,对每一个结果都进行扩充处理,对于i‘的半径在R内部以及外部这种确定的情况一次循环直接退出,其他两种扩充,不需要if语句
            while((i-rl[i])>-1&&(i+rl[i])<rl.length){
                if(geeArr[i-rl[i]]==geeArr[i+geeArr[i]]){
                    rl[i]++;

                }else{
                    break;
                }
            }
            if(i+rl[i]>r){
                r=i+rl[i];
                c=i;
            }
        }
        return rl;

    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值