字符串-马拉车算法-5. 最长回文子串

2020-03-19 11:44:44

问题描述:

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

示例 1:

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

示例 2:

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

问题求解:

解法一:DFS

对于长度为n的字符串,回文子串的中心点的个数有2 * n - 1个,其中n个是字符表示回文为奇数的情况,n - 1个是字符之间的位置表示回文为偶数的情况。

可以使用dfs来枚举所有的中心点位置,记录最长的即可。

时间复杂度:O(n ^ 2)

    String res = "";
    public String longestPalindrome(String s) {
        int n = s.length();
        for (int i = 0; i < n; i++) {
            extend(s, i, i);
            extend(s, i, i + 1);
        }
        return res;
    }
    
    private void extend(String s, int i, int j) {
        if (i < 0 || j >= s.length() || s.charAt(i) != s.charAt(j)) return;
        if (j - i + 1 > res.length()) res = s.substring(i, j + 1);
        extend(s, i - 1, j + 1);
    }

 

解法二:马拉车算法

马拉车算法是解决最长回文子串的最优解,可以在线性时间复杂度内求解。上述的暴力算法有两个问题,一个是要分别讨论奇偶情况,一个是没有充分利用回文的特性。

马拉车算法在每个字符左右都插入一个不常用字符(例如'#',aaa -> #a#a#a#),这样就只有长度为奇数的情况了,因为任意两个连续的字符都不相等。

另外,还需要维护一个目前回文到达的right_most位置,如果当前index在其范围内,可以使用前面计算的结果减少遍历。

时间复杂度:O(n)

    public String longestPalindrome(String s) {
        StringBuffer res = new StringBuffer();
        StringBuffer sb = new StringBuffer();
        sb.append("#");
        for (int i = 0; i < s.length(); i++) {
            sb.append(s.charAt(i)).append("#");
        }
        int n = sb.length();
        int[] dp = new int[n];
        dp[0] = 1;
        int right_most = 0;
        int mid = 0;
        for (int i = 1; i < n; i++) {
            int len = right_most >= i ? Math.min(right_most - i + 1, dp[mid * 2 - i]) : 1;
            while (i - len >= 0 && i + len <= n - 1 && sb.charAt(i - len) == sb.charAt(i + len)) len += 1;
            if (i + len - 1 > right_most) {
                right_most = i + len - 1;
                mid = i;
            }
            dp[i] = len;
        }
        int max_len = dp[0];
        for (int i = 0; i < n; i++) {
            if (dp[i] > max_len) {
                max_len = dp[i];
                mid = i;
            }
        }
        for (int i = mid - max_len + 1; i <= mid + max_len - 1; i++) {
            char c = sb.charAt(i);
            if (c == '#') continue;
            res.append(c);
        }
        return res.toString();
    }

  

 

posted @ 2020-03-19 12:00  hyserendipity  阅读(193)  评论(0编辑  收藏  举报