美文网首页
Manacher算法

Manacher算法

作者: APP叫我取个帅气的昵称 | 来源:发表于2020-11-10 15:10 被阅读0次
      // 预处理字符串,在两个字符之间加上#
        private String preHandleString(String s) {
            StringBuffer sb = new StringBuffer();
            int len = s.length();
            sb.append('#');
            for(int i = 0; i < len; i++) {
                sb.append(s.charAt(i));
                sb.append('#');
            }
            return sb.toString();
        }
    
        // 寻找最长回文字串
        public String findLongestPlalindromeString(String s) {
            // 先预处理字符串
            String str = preHandleString(s);
            // 处理后的字串长度
            int len = str.length();
            // 右边界
            int rightSide = 0;
            // 右边界对应的回文串中心
            int rightSideCenter = 0;
            // 保存以每个字符为中心的回文长度一半(向下取整)
            int[] halfLenArr = new int[len];
            // 记录回文中心
            int center = 0;
            // 记录最长回文长度
            int longestHalf = 0;
            for(int i = 0; i < len; i++) {
                // 是否需要中心扩展
                boolean needCalc = true;
                // 如果在右边界的覆盖之内
                if(rightSide > i) {
                    // 计算相对rightSideCenter的对称位置
                    int leftCenter = 2 * rightSideCenter - i;
                    // 根据回文性质得到的结论
                    halfLenArr[i] = halfLenArr[leftCenter];
                    // 如果超过了右边界,进行调整
                    if(i + halfLenArr[i] > rightSide) {
                        halfLenArr[i] = rightSide - i;
                    }
                    // 如果根据已知条件计算得出的最长回文小于右边界,则不需要扩展了
                    if(i + halfLenArr[leftCenter] < rightSide) {
                        // 直接推出结论
                        needCalc = false;
                    }
                }
                /* 中心扩展 */
                if(needCalc) {
                    int left = i - 1 - halfLenArr[i];
                    int right =  i + 1 + halfLenArr[i];
                    while( left >= 0 && right  < len) {
                        if(str.charAt(right) == str.charAt(left)) {
                            halfLenArr[i]++;
                        } else {
                            break;
                        }
                    }
                    // 更新右边界及中心
                    rightSide = i + halfLenArr[i];
                    rightSideCenter = i;
                    // 记录最长回文串
                    if(halfLenArr[i] > longestHalf) {
                        center = i;
                        longestHalf = halfLenArr[i];
                    }
                }
            }
            // 去掉之前添加的#
            StringBuffer sb = new StringBuffer();
            for(int i = center - longestHalf + 1; i <= center + longestHalf; i += 2) {
                sb.append(str.charAt(i));
            }
            return sb.toString();
        }
    

    相关文章

      网友评论

          本文标题:Manacher算法

          本文链接:https://www.haomeiwen.com/subject/hcdjbktx.html