Leetcode C++《热题 Hot 100-24》5.最长回文子串

Leetcode C++《热题 Hot 100-24》5.最长回文子串

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

示例 1:

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

示例 2:

输入: “cbbd”
输出: “bb”

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

  1. 思路
  • 方案1:采用动态规划, dp的值表示是否为回文子串,或者子串长度均可,时间复杂度和空间复杂度都是n*n
  • if s[i] == s[j], dp[i][j] = dp[i-1][j+1]
  • 方案2:基于方案1,想出了中心扩展法,任何一个字符都有可能处于回文子串的中心,根据该字符向两边扩展,时间复杂度为n*n,空间复杂度为O(1)
  • 方案3:
    • 据说有一个方案manacher时间复杂度和空间复杂度都是n,必须学习实现:https://leetcode-cn.com/problems/longest-palindromic-substring/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-bao-gu/。
    • 利用回文串的对称性:C 和 R 所对应的回文串是当前循环中 R 最靠右的回文串。
    • 也可以参考这个链接https://www.cnblogs.com/grandyang/p/4475985.html 太难理解了,哭泣,有图看会好理解一点点。
  1. 代码
class Solution {
public:
    //方案3
    string longestPalindrome(string s) {
        string str = addSomeChar(s);
        int c = 0, r = 0, maxLen=0, maxC=0;
        vector<int> p;
        for (int i = 0; i < str.length(); i++) {
            p.push_back(0);
        }
        for (int i = 1; i < str.length(); i++) {
            int other_i = 2 * c - i;
            if (other_i >=0 && r > other_i) {
                p[i] = min (r - i, p[other_i]); //利用回文字符串的对称性hh
            } else {
                p[i] = 1;  //因为两边有#
            }
            while(str[i-p[i]]==str[i+p[i]]) {
                p[i]++;  //这个太妙了,而且i也不用动
            }
            if (i+p[i] > r) {
                c = i;
                r = i+p[i];
                if (maxLen < p[i]) {
                    maxLen = p[i];
                    maxC = i;
                }
            }
        }
        return  s.substr((maxC-p[maxC])/2, p[maxC]-1);
    }

    string addSomeChar(string s) {
        string res = "^";
        for (int i = 0; i < s.length(); i++) {
            res += "#";
            res += s[i];
        }
        res += "#$";
        return res;
    }
    //方案2:
    /*string longestPalindrome(string s) {
        if (s == "")
            return "";
        int maxLength = 1;
        int maxLeft = 0;
        int maxRight = 0;
        for (int i = 0; i < s.length(); i++) {
            //假设最大回文子串包含s[i],首先把连续的相同的字符聚集在一起
            int left = i, right = i;
            for (int j = i+1; j < s.length(); j++) {
                if (s[j] != s[i]) {
                    right = j-1;
                    break;
                } else
                    right++;
            }
            for (int j = i-1; j >= 0; j--) {
                if (s[j] != s[i]) {
                    left = j+1;
                    break;
                } else
                    left--;
            }
            //cout << s[i] << " " << left << " " << right << " " << endl;

            int add = 0;
            for (int j = 0; j < s.length()-right-1; j++) {
                //cout << "&&&&& " << j << endl;
                if ((left-1-j) < 0) {
                    //cout << "&&&&&11 " << j << endl;
                    break;
                }
                    
                if (s[right+1+j] != s[left-1-j]) {
                    left = left-j;
                    right = right+j;
                    add = 0;
                    //cout << "&&&&&22 " << j << endl;
                    break;
                } else {
                    add++;
                    //cout << "&&&&&33 " << j << endl;
                }
            }
            if (add != 0) {
                left = left - add;
                right = right + add;
            }
            if ((right-left+1) > maxLength) {
                maxLength = right-left+1;
                maxLeft = left;
                maxRight = right;
            }
            
            //cout << s[i] << " " << s.substr(left, right-left+1) << endl;
        }
        return s.substr(maxLeft, maxLength);
    }*/
};
发布了205 篇原创文章 · 获赞 8 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Alexia23/article/details/104161422