zoukankan      html  css  js  c++  java
  • 字符串-马拉车算法-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();
        }
    

      

  • 相关阅读:
    蓝桥杯历届试题 打印十字图 文字图形
    Cuckoo Hashing
    2006 飞行员配对(二分图最大匹配)
    Bad Hair Day(求数组中元素和它后面离它最近元素之间的元素个数)
    2019CCPC江西省赛
    字典树系统学习
    ac自动机学习
    项目管理(把与某点相邻边分为两类 是复杂度降为(n^(3/2))
    Ultra-QuickSort(离散化)
    Chika and Friendly Pairs(莫队+树状数组+离散化+预处理上下界)
  • 原文地址:https://www.cnblogs.com/hyserendipity/p/12523295.html
Copyright © 2011-2022 走看看