leetcode 5. Longest Palindromic Substring

题目:Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.

 

题目解析:做题一定不要陷入惯性思维,要注重审题,从题目出发。不要看到题以为跟之前的题类似就想也不想就套之前的做法。可能题目稍微一变就要gg。要么是做错要么是简单的问题用了复杂的办法; 就比如这道题跟Longest palindromic subsequence类似,然后我就在这道题用了同样的解法,果然gg了。往事不堪回首。。。。。

 

①:判断最长的回文子串,暴力是遍历所有子串,时间复杂度O(N^2);

判断长度为l,从i开始的子串是不是回文字符串:当且仅当dp[l][i] = (s[i] == s[i+l-1] && dp[l-2][i+1]) 

class Solution {
public:
    string longestPalindrome(string s) 
    {
        int len = s.size() ;
        if(len == 0) return "" ;
        vector<vector<int>> dp(len + 1 , vector<int>(len , 0));
        for(int i = 0 ; i < len ; i++)
        {
            dp[0][i] = 1 ;
            dp[1][i] = 1 ;
        }
        
        string res = string(1 ,s[0]) ;
        for(int l = 2 ; l <= len ; l++)
        {
            for(int i = 0 ; i + l <= len; i++)
            {
                dp[l][i] = (s[i] == s[i+l-1] && dp[l-2][i+1]) ;
                if(dp[l][i] && l > res.size()) res = s.substr(i , l) ; 
            }
        }
        return res ;
    }
};

  

优化:其实可以看出当dp[l][i]不是回文字符串时,dp[l+1][i-1]....就不可能是回文字符串了。可以省略那些字符串的判断,减小时间复杂度。所以可以遍历i,从i的两边遍历以i为中心的最长回文字符串是多少?

class Solution {
public:
    string longestPalindrome(string s) 
    {
        int len = s.size() ;
        
        int pos = 0 ;
        int maxl = 0 ;
        string res = "" ;
        for(int i = 0 ; i < len ; i++)
        {
            //判断以i为中心的最长回文串,注意这回文串长度为奇数
            int l = i , r = i ;
            while(l > 0 && r < len - 1 && s[l-1] == s[r + 1]) 
            {
                l-- ;
                r++ ;
            }
            if(r - l + 1 > res.size()) res = s.substr(l , r - l + 1) ;
            
            if(i == len - 1 || s[i] != s[i+1]) continue ;
            
            //还要判断偶数长度的回文字符串
            l = i ; 
            r = i + 1 ;
            while(l > 0 && r < len - 1 && s[l-1] == s[r+1])
            {
                l-- ;
                r++ ;
            }
            if(r - l + 1 > res.size()) res = s.substr(l , r - l + 1) ;
        }
        return res ;
    }
};            

  

进一步优化:这是判断偶数字符串的时候想到的,当从i开始遍历的时候,如果[i,j]是一串相同子串,可以从这一串相同子串的两边开始遍历,i可以跳到j+1.因为i为[i+1,j]时,其最长回文字符串的长度不超过j-i+1;

class Solution {
public:
    string longestPalindrome(string s) 
    {
        int len = s.size() ;
        
        int pos = 0 ;
        int maxl = 0 ;
        string res = "" ;
        while(pos < len)
        {
            if((len - pos) * 2 <= maxl) break ;
            int l = pos , r = pos ;
            while(r < len - 1 && s[r+1] == s[r]) r++ ;
            pos = r + 1 ;
            
            while(l > 0 && r < len - 1 && s[l-1] == s[r+1])
            {
                l-- ;
                r++ ;
            }
            
            if(r - l + 1 > maxl) 
            {
                maxl = r - l + 1 ;
                res = s.substr(l , r - l + 1) ;
            }
        }
        return res ;
    }
};

  

posted on 2020-04-10 10:13  景行cmy  阅读(85)  评论(0)    收藏  举报