LeetCode | 5.最长回文子串

给你一个字符串 s,找到 s 中最长的回文子串。

如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。

示例 1:

输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。

示例 2:

输入:s = "cbbd"
输出:"bb"

提示:

  • 1 <= s.length <= 1000
  • s 仅由数字和英文字母组成

思路:

方案一:中心扩展算法。
  感觉就是枚举,对每一个字符向两边遍历,获取以该字符为中心的最长回文子串。
  由于回文子串可能是偶数,所以也要遍历 i, i + 1, 向两边扩展的情况。
  时间复杂度 O(n2)

string longestPalindrome(string s) {
    string res = "";
    for (int i = 0; i < s.size(); i++) {
        string res1 = helper(s, i, i);
        string res2 = helper(s, i, i + 1);
        if (res.size() < res1.size())
            res = res1;
        if (res.size() < res2.size())
            res = res2;
    }
    return res;
}
string helper(string &s, int l, int r) {
    while (l >= 0 && r < s.size() && s[l] == s[r]) {
        l--;
        r++;
    }
    return s.substr(l + 1, r - l - 1);
}

方案二:Manacher 算法

  在中心扩展算法的基础上记录了右臂在最右边的回文子串,记录了已经遍历过的字符的回文子串。
  在遍历到新的字符时,根据回文串对称的性质,减少遍历次数。
  用特殊字符进行填充,把偶数回文变成奇数回文
  时间复杂度 O(n)

class Solution {
public:
    int expand(const string& s, int left, int right) {
        while (left >= 0 && right < s.size() && s[left] == s[right]) {
            --left;
            ++right;
        }
        return (right - left - 2) / 2;
    }

    string longestPalindrome(string s) {
        int start = 0, end = -1;
        string t = "#";
        for (char c: s) {
            t += c;
            t += '#';
        }
        t += '#';
        s = t;

        vector<int> arm_len;
        int right = -1, j = -1;
        for (int i = 0; i < s.size(); ++i) {
            int cur_arm_len;
            if (right >= i) {
                int i_sym = j * 2 - i;
                int min_arm_len = min(arm_len[i_sym], right - i);
                cur_arm_len = expand(s, i - min_arm_len, i + min_arm_len);
            } else {
                cur_arm_len = expand(s, i, i);
            }
            arm_len.push_back(cur_arm_len);
            if (i + cur_arm_len > right) {
                j = i;
                right = i + cur_arm_len;
            }
            if (cur_arm_len * 2 + 1 > end - start) {
                start = i - cur_arm_len;
                end = i + cur_arm_len;
            }
        }

        string ans;
        for (int i = start; i <= end; ++i) {
            if (s[i] != '#') {
                ans += s[i];
            }
        }
        return ans;
    }
};

方案三:动态规划

string longestPalindrome(string s) {
    int n = s.size();
    vector<vector<int>> dp(n, vector<int>(n)); // dp[i][j] 表示 s[i..j] 是否是回文子串
    for (int i = 0; i < n; ++i) {
        dp[i][i] = true; // 初始化,所有长度为1的子串都是回文串
    }

    int len = 1, begin = 0;
    for (int length = 2; length <= n; length++) {
        for (int left = 0; left < n; ++left) {
            int right = left + length - 1;
            if (right >= n)
                break;
            if (s[left] == s[right]) {
                if (right - left == 1) // 长度为 2 的子串
                    dp[left][right] = true;
                else
                    dp[left][right] = dp[left + 1][right - 1];
            }
            if (dp[left][right] && right - left + 1 > len) {
                len = right - left + 1;
                begin = left;
            }
        }
    }
    return s.substr(begin, len);
}

动态规划另一种实现:

string longestPalindrome(string s) {
    int n = s.size();
    vector<vector<int>> dp(n, vector<int>(n)); // dp[i][j] 表示 s[i..j] 表示的回文子串长度
    for (int i = 0; i < n; ++i) {
        dp[i][i] = 1; // 初始化,所有长度为1的子串都是回文串
    }

    int len = 1, begin = 0;
    for (int i = n - 2; i >= 0; --i) {
        for (int j = i + 1; j < n; ++j) {
            if (s[i] == s[j] && (dp[i + 1][j - 1] != 0 || j - i == 1)) {
                    dp[i][j] = dp[i + 1][j - 1] + 2;
            }
            if (dp[i][j] > len) {
                len = dp[i][j];
                begin = i;
            }
        }
    }
    return s.substr(begin, len);
}

类似题目:最长回文子序列

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇