马拉车Manacher算法总结

马拉车Manacher算法总结

  • 专门解决回文问题的算法!
  • 记录每个元素半径长度以及最右的位置R并保持更新这两个变量!
  • 记录对应的中点位置C

给一个字符串,首先找出对称轴元素!不过元素为偶数个的时候对称轴会不存在!如何把奇偶统一?在字符串之间加#字符全转换为奇个数!

回文半径数组----prrArr[]

回文半径数组、之前扩地所有所到达的最右边界位置以及对应的中心点

  • 有了R,C,prrArr[]信息,就要判断i的位置

第一种情况 i > R在外部

很明显,直接向外扩张,更新R

第二种情况 i < R 在R内部

1、半径也在R内

直接找i的对称点i’,两个的答案是一样的!

2、回文一部分在半径外部

看图得知 X==Y,Y = =Z,P != X !=Z

答案就是i~R

第三种压线了!

判断R后一个和R‘前一个是否相等就行了!

class Solution5 {
    public static void main(String[] args) {
        String s = "babad";
        Solution5 solution = new Solution5();
        String s1 = solution.longestPalindrome(s);
        System.out.println(s1);
    }
    public String longestPalindrome(String s) {
        //把字符串处理成adb--->#a#b#b#
        StringBuffer t = new StringBuffer("#");
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            t.append(c);
            t.append('#');
        }
        s = t.toString();
        //定义
        //回文半径数组
        int[] prrArr = new int[s.length()];
        int Center = 0;
        int Right = -1;
        int start = 0;
        int maxLen = 0;
        //int max = Integer.MAX_VALUE;
        for (int i = 0; i < s.length(); i++) {
            //i在不在最大半径里面?在的话就半径加到Right!
            //能不能继续向下加先不着急!不在R里面的话就只能+1
            prrArr[i] = Right > i ?Math.min(prrArr[2*Center - i],Right - i) :1;
            while(i + prrArr[i] < s.length() && i- prrArr[i] > -1){
                if (s.charAt(i + prrArr[i]) == s.charAt(i - prrArr[i])){
                    prrArr[i]++;
                }else {
                    break;
                }
            }
            //更新Right
            if(i+ prrArr[i] > Right){
                Right = i + prrArr[i];
                Center = i;
            }
            //max = Math.max(max, prrArr[i]);
            if (prrArr[i]*2 + 1> maxLen - start){
                start = i - prrArr[i];
                maxLen = i + prrArr[i];
            }

        }
        StringBuffer ans = new StringBuffer();
        for (int i = start + 1; i <= maxLen - 1; ++i) {
            if (s.charAt(i) != '#') {
                ans.append(s.charAt(i));
            }
        }
        return ans.toString();
        //return s;

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值