力扣刷题:5、最长回文子串

题目要求

给你一个字符串 s,找到 s 中最长的回文子串。
(回文串就是正着读和反着读都一样的字符串)

  • 1 <= s.length <= 1000
  • s 仅由数字和英文字母(大写和/或小写)组成

版本一:一种凭借直觉但是超时的算法

class Solution {
    
    
public:
    string longestPalindrome(string s) {
    
    
        unsigned maxSize = 0;
        string maxHuiWen;
        for (size_t i = 0; i < s.length(); i++)
        {
    
    
            for (size_t j = i+1; j <= s.length(); j++)
            {
    
    
                if ((j-i > maxSize) && isHuiWen(s.substr(i, j-i)))
                {
    
    
                    maxSize = j - i;
                    maxHuiWen = s.substr(i, j - i);
                }
            }
        }
        return maxHuiWen;
    }
    bool isHuiWen(const string &s)
    {
    
    
        if (string(s.rbegin(), s.rend()) == s)
        {
    
    
            return true;
        }
    	return false;
    }
};

整体思路

先构造一个判断字符串是否是回文串的函数。对于给定的字符串s,找出该s的所有子串,调用回文判断函数找出最长的回文子串。

版本二:动态规划

class Solution {
    
    
public:
    string longestPalindrome(string s) {
    
    
        int lenth = s.length(), maxlenth = 0;
        string maxHuiWen;
        //初始化dp表
        bool** dp;
        dp = new bool*[lenth];
        for (size_t i = 0; i < lenth; i++)
        {
    
    
            dp[i] = new bool[lenth];
        }
        for (size_t i = 0; i < lenth; i++)
        {
    
    
            for (size_t j = i; j < lenth; j++)
            {
    
    
                if (i == j)
                {
    
    
                    dp[i][j] = true;
                }
                else
                    dp[i][j] = false;
            }
        }
        //当使用递减for循环时,不能使用unsigned i>=0;
        for (int i = lenth-1; i >= 0; i--)
        {
    
    
            for (int j = lenth-1; j >= i; j--)
            {
    
    
                //首尾相同
                if (s[i] == s[j])
                {
    
    
                    //子串是回文串 或者 没有子串
                    if (i+1 >= j-1 || dp[i+1][j-1] == true)
                    {
    
    
                        dp[i][j] = true;
                        if (j - i + 1 > maxlenth)
                        {
    
    
                            maxlenth = j - i + 1;
                            maxHuiWen = s.substr(i, j - i + 1);
                        }
                    }
                }
            }
        }
        return maxHuiWen;
    }
};

整体思路

对于一个回文串,它的首尾字符是相同的。并且在去掉首尾字符后,剩下的字符组成的字符串还是一个回文串。利用这个性质进行动态规划。
首先初始化dp表,设置给定字符串中长度为1的子串为回文串,也就是true。
状态转移:对于str[i,j] (从i开始到j结束) 的字符子串。如果第i位和第j位的字符首尾相同,并且从i+1到j-1的子串是回文串,则该子串为回文串。
从dp表的尾端开始构造到头端,最后将整个dp表构造完毕。

学到了什么

1、重新熟悉了动态规划的思想和dp表的构建
2、对于递减的for循环,不能用unsigned i 以及 i>0 来控制循环的结束。因为unsigned始终大于0.此时只能使用int来控制for循环的结束。
3、二维数组的动态申请方法:

bool** dp;
dp = new  bool*[lenth]; //提前给定一个lenth
for (size_t i = 0; i < lenth; i++)
{
    
    
	dp[i] = new bool[lenth];
}

猜你喜欢

转载自blog.csdn.net/youyadefeng1/article/details/113404103