leetcode 5 最长回文子串

 搞暴力算法也能搞出来,而且不大困难,这个题最主要的问题是第一次接触了动态规划的东西,具有一定的历史意义。下面先贴暴力代码

class Solution 
{
public:
    string longestPalindrome(string s) 
    {
        int n = s.length();
        int i = 0;
        int j = n-1;
        int maxSize = 1;
        string maxString = s.substr(0,1);
        for(i = 0 ; i < n-1  ; i++)
        {
            for(j = n-1 ; j > i ; j--)
            {
                if(s[i] == s[j])
                {
                    int k = 0;
                    while(s[i+k] == s[j-k] && i+k<j-k)
                    {
                        k++;
                    }
                    if(i+k == j-k || i+k == j-k+1)
                    {
                        if(i == 0 && j == n-1)
                        return s;                       
                        else if(j-i+1 > maxSize)
                        {
                            maxSize = j-i+1;
                            cout<<maxSize<<endl;                   
                            maxString= s.substr(i,j-i+1);
                        }
                    
                    }
                }
            }          
        
        }
        return maxString;
    }
};

下面是动态规划代码

class Solution 
{
public:
    string longestPalindrome(string s) 
    {
        int n = s.length();
        vector<vector<bool>> db(n, vector<bool>(n));
        string maxSize;
        int max = 0;
        for(int l = 0; l < n ; l++)
        {
            for(int i = 0 ; i + l <n ;i++)
            {
                int j = i + l;
                if(l == 0)
                {
                    db[i][j] = true;
                }
                else if(l == 1)
                {
                    db[i][j] = (s[i] == s[j]);
                }
                else
                {
                    db[i][j] = ((db[i+1][j-1]) && (s[i] == s[j]));
                }
                if(db[i][j] && (l+1 > max))
                {
                    max = l;
                    maxSize = s.substr(i,l+1);
                }
            }            
        }
        return maxSize;
    }
};

最重要的还是写出状态转移方程和边界条件。这一题的状态可以抽象为i,j之间的子串是否是回文子串,也就是一个bool变量。而最关键的在于,如果一个回文子串左右一个字符相等,那么也是回文子串,否则则不是回文串,这一点就让我们能够写出最后的状态转移方程。边界方程也相对好理解,如果长度为1,则一定是回文子串,若长度为2,两个字符串相等则为回文子串。这么一抽象还是很好理解的。

下面写下中心扩展算法,这个方法其实写暴力算法的时候有想到过,但是没写出来,总的来说一个回文子串一定有一个中心,可以是一个字符,也可以是两个字符,基于这个中心进行对称的拓展。基于这样一个情况,可以对所有的中心进行遍历,然后就能够遍历出所有可能出现的回文情况。

贴代码,这个写了最久,nnd,小错特别多

class Solution 
{
public:
 pair<int, int> expandAroundCenter(const string& s, int left, int right)
        {
            while(left >= 0 && right < s.length() && s[left] == s[right])
            {
                left--;
                right++;
            }
            cout<<left+1<<right-1<<endl;
            return {left+1,right-1};
        }
    string longestPalindrome(string s) 
    {     
    string maxSize = "";
    int start =0;
    int end = 0;
    for(int i = 0 ; i < s.length() ; i++)
    {
        auto [left1,right1] = expandAroundCenter(s,i,i);
        auto [left2,right2] = expandAroundCenter(s,i,i+1);
        if(right1-left1 > right2-left2)
        {
            start = left1;
            end = right1;
        }
        else
        {
            start = left2;
            end = right2;    
        }
        if(end-start+1 > maxSize.length())
        {
            maxSize = s.substr(start,end-start+1);
        }
    }
    return maxSize;
    }
};

 

posted @ 2021-03-02 19:57  zhaohhhh  阅读(67)  评论(0)    收藏  举报