5. 最长回文子串

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。

示例 1:

输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
示例 2:

输入: "cbbd"
输出: "bb"

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-palindromic-substring
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

动态规划,但是时间复杂度O(n^2),勉强跑过

class Solution {
    private static final String EMPTY = "";

    /**
     * 动态规划
     *
     * 1. 状态定义
     *  f(x) = 以x元素坐标为中心的回文
     * 2. 状态转移方程
     *  f(x) = f(2 * x - i) + f(x) + f(i), x = 0 ~ i
     *
     * 时间复杂度O(n^2),此解超时
     *
     * @param s
     * @return
     */
    public String longestPalindrome(String s) {
        int len = s.length();
        // 加上这个判断勉强跑过了
        if (len == 0 || s.replace(String.valueOf(s.charAt(0)), "").length() == 0) {
            return s;
        }
        String[] palindrome = new String[2 * len + 1];
        String max = "";
        for (int i = 0; i < 2 * len + 1; i++) {
            char iCh = getChar(s, i);
            setChar(palindrome, s, i);
            for (int j = 0; j <= i; j++) {
                int before = 2 * j - i;
                if (before < 0 || getChar(s, before) != iCh || !needPalindrome(j, i, palindrome[j])) {
                    continue;
                }
                palindrome[j] = iCh + (palindrome[j] == null ? "" : palindrome[j]) + iCh;
                if (palindrome[j].length() > max.length()) {
                    max = palindrome[j];
                }
            }
        }
        return max.replace(String.valueOf(Character.MIN_VALUE), "");
    }

    /**
     * 只有连续的元素是回文才能算是回文
     *
     * @param position 回文中心
     * @param index 最外的字符
     * @param palindrome 当前的回文
     * @return
     */
    private boolean needPalindrome(int position, int index, String palindrome) {
        int curLen = palindrome == null ? 0 : palindrome.length();
        return index - position == curLen / 2 + 1;
    }

    /**
     * index是填充后的坐标,s是为填充的字符串,获取对应的字符需要进行转换
     *
     * @param s
     * @param index
     * @return
     */
    private char getChar(String s, int index) {
        if (index % 2 == 0) {
            return Character.MIN_VALUE;
        }
        return s.charAt(index / 2);
    }

    private void setChar(String[] palindrome, String s, int index) {
        if (index % 2 == 0) {
            palindrome[index] = EMPTY;
        } else {
            palindrome[index] = String.valueOf(s.charAt(index / 2));
        }
    }
}
运行效率

动态规划v2

class Solution {
    /**
     * 动态规划
     *
     * 1. 状态定义
     *  f[begin][end]: 坐标i到j字符串是否是回文
     *
     * 2. 状态转移方程
     *  f[begin][end] = f[begin+1][end-1] && (s[begin] == s[end]), (begin <= end)
     *
     * @param s
     * @return
     */
    public String longestPalindrome(String s) {
        if (s.length() == 0) {
            return s;
        }
        int maxLen = 1, maxLeft = 0, maxRight = 0;
        boolean[][] f = new boolean[s.length()][s.length()];
        // 初始状态
        for (int i = 0; i < s.length(); i++) {
            // 单个元素都是回文
            f[i][i] = true;
        }
        for (int end = 1; end < s.length(); end++) {
            for (int begin = 0; begin < end; begin++) {
                if (s.charAt(begin) != s.charAt(end)) {
                    continue;
                }
                if (end - begin < 3 || f[begin + 1][end - 1]) {
                    f[begin][end] = true;
                    if (end - begin + 1 > maxLen) {
                        maxLen = end - begin + 1;
                        maxLeft = begin;
                        maxRight = end;
                    }
                }
            }
        }
        return s.substring(maxLeft, maxRight + 1);
    }
}
运行效率

类似动态规划,比较优的O(n^2)算法

class Solution {
    private int maxLen = 1; // 最大长度
    private int resLeft = 0;
    private int resRight = 0;

    /**
     * 分别以每个节点为中心进行扩散,记录最大的回文
     *
     * @param s
     * @return
     */
    public String longestPalindrome(String s) {
        if (s.length() == 0) {
            return s;
        }
        for (int i = 0; i < s.length(); i++) {
            // 以i为中心,奇数元素的回文
            searchPalindrome(s, i - 1, i + 1);
            // 以i和i+1为中心,偶数元素的回文
            searchPalindrome(s, i, i + 1);
        }
        return s.substring(resLeft, resRight + 1);
    }

    private void searchPalindrome(String s, int left, int right) {
        while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
            left--;
            right++;
        }
        if (right - left - 1 > maxLen) {
            maxLen = right - left - 1;
            resLeft = left + 1;
            resRight = right - 1;
        }
    }
}
运行效率

时间复杂度O(n)的Manacher算法,难度较大,还未实现

你可能感兴趣的:(5. 最长回文子串)