最长回文子串动态规划_【算法刷题】最长回文子串

点击上方蓝字关注我,我们一起学编程欢迎小伙伴们分享、转载、私信、赞赏

最长回文子串

1. 暴力枚举法2. 中心扩展法3. 动态规划法4. Manacher 算法

所谓回文串,就是正序和逆序都相同的子串。(上海自来水来自海上)子串是原字符串的连续部分,这区别于子序列。

1. 暴力枚举法

时间复杂度:O(n^3)
空间复杂度:O(1)

class Solution {
public:
    string longestPalindrome(string s){
        int len = s.size();

        if (len <= 1) {
            return s;
        }

        int maxLen = 1;    /* 回文串的最大长度 */
        int begin = 0;     /* 回文串的起始下标 */

        for (int i = 0; i 1; ++i) {
            /* 从大于最大长度的位置开始遍历 */
            for (int j = i + maxLen ; j                 if (isPalindrome(s, i, j)) {
                    maxLen = j - i + 1;
                    begin = i;
                }
            }
        }

        return s.substr(begin, maxLen);
    }

    /* 判断是否为回文串 */
    bool isPalindrome(const string& s, int start, int end){
        bool ispalindrome = true;

        while (start             if (s[start++] != s[end--]) {
                ispalindrome = false;
                break;
            }
        }

        return ispalindrome;
    }
};

2. 中心扩展法

分析:

枚举所有可能的回文子串的中心位置,中心位置可能是一个字符(奇数长度),也可能是两个相邻的字符(偶数长度)。

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

class Solution {
public:
    string longestPalindrome(string s){
        int len = s.size();

        if (len <= 1) {
            return s;
        }

        int maxLen = 1;    /* 回文串的最大长度 */
        int begin = 0;     /* 回文串的起始下标 */

        for (int i = 0; i 1; ++i) {
            int oddLen = expandAroundCenter(s, i, i);         /* 回文串的中心为单个字符 */
            int evenLen = expandAroundCenter(s, i, i + 1);    /* 回文串的中心为两个相邻的字符 */
            int curMaxLen = max(oddLen, evenLen);

            if (curMaxLen > maxLen) {
                maxLen = curMaxLen;
                begin = i - (maxLen - 1) / 2;    /* 计算当前最大回文串的起始下标 */
            }
        }

        return s.substr(begin, maxLen);
    }

    /* 从中心往两边扩展,寻找最长回文子串的长度 */
    int expandAroundCenter(const string& s, int left, int right){
        int len = s.size();
        int i = left;
        int j = right;

        while (i >= 0 && j             if (s[i] == s[j]) {
                --i;
                ++j;
            } else {
                break;
            }
        }

        return j - i - 1;
    }
};

3. 动态规划法

分析:

状态:dp[i][j] 表示子串 s[i...j] 是否为回文子串;
状态转移方程:dp[i][j] = (s[i] == s[j]) && dp[i + 1][j - 1]
初始化:dp[i][i] = true
输出:在得到一个状态的值为 true 的时候,记录起始位置和长度,填表完成以后再截取。

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

class Solution {
public:
    string longestPalindrome(string s){
        int len = s.size();

        if (len <= 1) {
            return s;
        }

        int maxLen = 1;    /* 回文串的最大长度 */
        int begin = 0;     /* 回文串的起始下标 */

        vector<vector<bool>> dp(len, vector<bool>(len, true));

        for (int j = 1; j             for (int i = 0; i                 if (s[i] != s[j]) {
                    dp[i][j] = false;
                } else {
                    dp[i][j] = (j - i <= 2) ? true : dp[i + 1][j - 1];
                }

                if (dp[i][j] && j - i + 1 > maxLen) {
                    maxLen = j - i + 1;
                    begin = i;
                }
            }
        }

        return s.substr(begin, maxLen);
    }
};

4. Manacher 算法

时间复杂度为 O(n) 。该算法十分复杂,有兴趣的童鞋可以自己查阅相关资料。

63190965b9d02e21299dbdd1a800a127.png

长按识别关注

*编程笔记本*

来都来了,点个在看再走吧~~~

71a5a3410f74a4c9c17df209b96ed916.gif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值