最长回文子串

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

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

示例 1:

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

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

提示:

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

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

解题思路1:动态规划

见注释。

code

class Solution {
public:
    //朴素写法:遍历每一个子串并判断是否为回文串

    //o(n^2)遍历以及O(n)的判断时间复杂度
    //一种是优化O(n ^ 2),尝试用双指针
    //双指针or滑动窗口:同一端出发,遇到不是回文串就退出?显然不行
    //从数组两端出发,也不行,向那边移动呢?
    //一种是优化回文子串的判断
    //优化回文子串的判断时间:利用已有的回文子串的信息进行辅助判断
    //"aba" -> "xabax" or "xabay"
    
    //动态规划来利用已有的信息辅助判断回文子串
    //状态表示:f[i,j]子串[i,j]是否为回文串
    //状态转移:f[i,j] = f[i+1,j-1] && (s[i] == s[j])
    //初始化:单个字符必然是回文串 && 两个字符的也要单独判断
    //遍历顺序:先初始化f[i+1,j-1],会先使用i+1的值,因此i要倒序遍历,j可以顺序遍历

    string longestPalindrome(string s) {
        
        int n = s.size();
        vector<vector<int>> f(n,vector<int>(n,0));

        for(int i = 0;i < n;i ++) f[i][i] = 1;

        for(int i = n-1;i >= 0;i --)
        {
            for(int j = i + 1;j < n;j ++)
            {
                if(j - i == 1 && s[i] == s[j]) f[i][j] = 1;
                else if(f[i+1][j-1] && (s[i] == s[j])) f[i][j] = 1;
            }
        }
        
        pair<int,int> longest = {0,0};
        int i,j;
        for(i = 0;i < n;i ++)
        {
            for(j = i;j < n;j ++)
            {
    
                if(f[i][j] && j - i + 1 >= longest.second - longest.first + 1) longest = {i,j};
                
            }
        }
        
        
        return s.substr(longest.first,longest.second - longest.first + 1);

    }
};

解题思路2:中心扩散法

使用动态规划的空间复杂度是\(O(n^2)\)。接下来尝试对动态规划的时间复杂度进行优化。为了利用原有的回文子串的信息,我们只需要不断向外扩展两个字符串即可,就可以找到当前为中心开始向外扩展的可以到达的最长的字符串,中心可以是单个的字符串也可以是两个相同的字符串。

code

class Solution {
public:
   
    pair<int,int> diffusion(string & s,int i,int j)
    {
        while(i >= 0 && j < s.size())
        {
            if(i - 1 >= 0 && j + 1 < s.size() && s[i-1] == s[j+1]) i --,j++;
            else break;     
        }

        return {i,j};
    }
    string longestPalindrome(string s) {
        
        int n = s.size();
        
        pair<int,int> longest;

        for(int i = 0;i < n;i ++)
        {
            pair<int,int> find;
            find = diffusion(s,i,i);
            if(find.second - find.first + 1 >= longest.second - longest.first + 1) longest = find;
            
            if(i + 1 < n && s[i] == s[i+1]) find = diffusion(s,i,i+1);
            if(find.second - find.first + 1 >= longest.second - longest.first + 1) longest = find;
            

        }

        return s.substr(longest.first,longest.second - longest.first + 1);


    }
};

解题思路3:马拉车算法

posted on 2023-03-11 21:31  huangxk23  阅读(14)  评论(0编辑  收藏  举报