Leetcode第5题 最长回文子串C++解法

没动态规划出来,就做不出来……

class Solution {
    
    
public:

    string longestPalindrome(string s) {
    
    
        int n=s.size();
        if(n<2)  return s;
        int dp[n][n],pos=0,len=1; 
        memset(dp,0,sizeof(dp));
        for(int i=1;i<n;++i)
        {
    
    
            dp[i][i]=1;
            dp[i][i-1]=1;
        }
        dp[0][0]=1;
        for(int i=n-2;i>=0;--i)
        {
    
    
            for(int j=n-1;j>i;--j)
            if(s[i]==s[j]){
    
    
                dp[i][j]=dp[i+1][j-1];
                if(dp[i][j]&&(j-i)>(len-1))
                    {
    
    pos=i;len=j-i+1;}
                }
        }
        return s.substr(pos,len);
    }
};

这种做法dp数组的i和j分别代表回文串两端的序号。官方解法则是从字符串长度和首序号出发。区别在于i、j如果是两段的序号的话,空间复杂度可以优化到O(N)。

实际上一开始我的做法是,先反转字符串,但是这种思路没做出来
再然后我想的是一遍遍历得出结果,异想天开了,思路是从头到尾分奇数回文串和偶数回文串分别进行验证
看了答案才知道以上两种都是可以做出来的。比较原字符串和反转字符串的话,相当于求最长公共子串,而我还陷在最长公共子序列里面,自然得不出来。
分别求奇数和偶数串则是陷入到一遍遍历里面,前面的结果会干扰到后面的结果的,正确就是按中心扩展法分别遍历奇数和偶数中心
最长公共子串解法

class Solution {
    
    
public:
    string longestPalindrome(string s) {
    
    
        int n=s.size();
        if(n<2)  return s;
        string rev(s);
        reverse(rev.begin(),rev.end());
        int dp[n][n];
        memset(dp,0,sizeof(dp));
        int pos=0,len=1;
        for(int i=0;i<n;++i)
        {
    
    
            for(int j=0;j<n;++j)
            {
    
    
                if(s[i]==rev[j]){
    
    
                if(i==0||j==0)
                    dp[i][j]=1;
                else
                    dp[i][j]=dp[i-1][j-1]+1;
                int t_len=dp[i][j];
                if(t_len>len&&j==(n-i-2+t_len))                
                    {
    
    len=t_len;pos=i-len+1;}
                }
            }
        }       
        return s.substr(pos,len);
    }
};

中心扩展法解法

class Solution {
    
    
public:

    string longestPalindrome(string s) {
    
    
        int n=s.size();
        if(n<2)  return s;
        int pos=0,len=1;
        for(int i=0;i<n;++i)
            for(int j=i;j<i+2&&j<n;++j){
    
    
                int t_len=maxstr(s,i,j);
                if(t_len>len)
                {
    
    len=t_len;pos=j-len/2;}
            }
        return s.substr(pos,len);        
    }


    int maxstr(string& s,int i,int j)
    {
    
    
        int res=0,n=s.size();
        while(i>=0&&j<n&&s[i]==s[j])
            {
    
    --i;++j;}
        return j-i-1;
    }
};

而如果解决了回文串的奇偶性,那么就不用分奇偶了,然而还是O(N^2),但马拉车算法可以通过优化达到(N),但也只有天才才能想出来了

猜你喜欢

转载自blog.csdn.net/meixingshi/article/details/113875696