字符串的最大回文子串

求给定的一个字符串中的最大回文子串
一般第一想到的方法应该就是循环,回文就是以某个字符为中心向两侧扩展,并且两侧对称。
这样的解决方法执行时间复杂度会是O( n 2 n^2 n2)。如何做到线性负责度呢。
那就是Manaker算法了。我这里只给出我的Java单个方法的实现,分析的内容可以参考给出的链接。

    public String longestPalindrome(String s) {
        // 首位分别添加'$', '@'防止边界异常
        StringBuilder t = new StringBuilder("$");
        for (int i = 0; i < s.length(); i++) {
            t.append('#');
            t.append(s.charAt(i));
        }
        t.append('#');
        t.append('@');
        
        int right = 0; // 最新回文子串右侧边界
        int center = 0; // 最新回文子串中心位置
        int len = t.length();
        int[] p = new int[len];
        
        for (int i = 1; i < len - 1; i++) {
            // 利用已经计算过的回文信息,加快运行时间
            // 在以center为中心回文范围内的i,可以利用回文性质,找到
            // 其对于center对称的点 '2 * center - i' 的回文数据,减少
            // 扩展次数,从而加快搜索
            if (i < right) p[i] = Math.min(p[2 * center - i], right - i);
            
            // 中心扩展,p[i] + 1 => 扩展的长度
            while (t.charAt(i - (p[i] + 1)) == t.charAt(i + (p[i] + 1)))  p[i]++;
            if (i + p[i] > right) { // 最新回文下表更新
                center = i;
                right = i + p[i];
            }
        }
        int longest = 0;
        int index = 0;
        for (int i = 1; i < p.length - 1; i++) {
            if (p[i] > longest) {
                longest = p[i];
                index = i;
            }
        }
        return s.substring((index - longest) / 2, (index + longest) / 2);
    }

参考:

  1. 基本概念
  2. Manaker算法
  3. leetcode上回文分析
  4. 其他比较详细的分析
    • 分析1
    • 分析2

你可能感兴趣的:(算法,编程之美)