LeetCode 005. Longest Palindromic Substring

5. Longest Palindromic Substring

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

Example:

Input: "babad"

Output: "bab"

Note: "aba" is also a valid answer.

Example:


Input: "cbbd"

Output: "bb"

class Solution {
public:
    string longestPalindrome(string s) {
    }
};
解题思路:
  • 自己的解题思路
自己采用的是 Brute Force ,然后通过不断优化算法,强行 AC 。一次次优化的过程,真的很有成就感。
思路很简单,就是采用两指针,从尾开始判别,如果是回文数,哪肯定是那次循环当作最长的回文子字符串,因此直接 break; 进入下个循环。
  • 别人的解题思路
Manacher’s Algorithm( 马拉车算法 ) 通过加入一些无关字符, eg:## 进行搜索;
DP 也可以做。
学习收获:
  • 优化暴力法。体验一次 强行 AC

附件:程序
1 、自己的程序:
一开始程序如下:这些都会出现 LTE 错误,主要是测试用例给的 string 很大。
class Solution
{
    public:
    string longestPalindrome(string s)
    {
        if(s.size() == 0) { return{}; }
        int max = 0;
        string res;
        for(int i = 0; i != s.size(); ++i)
        {
// 由于 j 每次都是查看最后一个位置,其实只需要从等于 s[i] 的最后一个位置开始
            for( auto j = s.size() ; j != i; --j)
            {
                if(isPalindrome(s, i, j))
                {
                    if(j - i > max)
                    {
                        max = j - i;
// 可以不需要每次取出 substr, 可以直接记录起始位置就行;因为有个 max ,所以可以就记开始位置就好
                         res = s.substr(i, j - i);
                    }
                    break;
                }
            }
        }
        return res;
    }
    // 这个可以优化,不需要全部倒序就能判别是否是回文字符串
    bool  isPalindrome (string s, int beg, int end)
    {
        string tem = s.substr(beg, end - beg);
        reverse(tem.begin(), tem.end());
        return s.substr(beg, end - beg) == tem?true:false;
    }
};
之后,改为
//NOTE :对于字符串的取值,可以直接 s[beg], 这样显得很整洁,虽然也是符号重载为迭代器实现的
bool isPalindrome(string s, int beg, int end)
    {
        while((end > beg) &&  *(s.begin() + beg) == *(s.begin() + end - 1) )
        {
            ++beg;
            --end;
        }
        if(end > beg) return false;
        else
        {
            return true;
        }
    }
通过几次优化,可以勉强通过程序,不过时间花费比较大, 509ms.
class  Solution
{
     public :
     string  longestPalindrome ( string  s )
     {
         if ( s . size ()  ==  0 )  {  return {};  }
         int  max  =  0 ;
         int  beg  =  0 ;
         for ( int  i  =  0 ;  i  !=  s . size ();  ++ i )
         {
             for ( auto  j  =  s . size ();  j  !=  i ;  -- j )
             {
                 j  =  s . find_last_of ( s [ i ],  j );
                 // 肯定会找到 j 的,最坏的情况 j==i; 对于找到的子字符串如果长度 <=max, 那么直接跳出循环
                 if ( j  +  1  -  i  <=  max )  {  break ;  }
                 if ( isPalindrome ( s ,  i ,  j  +  1 ))
                 {
                     max  =  j  +  1  -  i ;
                     beg  =  i ;
                     break ;
                 }
             }
         }
         return  s . substr ( beg ,  max );
     }
     bool  isPalindrome ( string  s ,  int  beg ,  int  end )
     {
         while (( end  >  beg )  &&  s [ beg ]  ==  s [ end  -  1 ])
         {
             ++ beg ;
             -- end ;
         }
         if ( end  >  beg )  return  false ;
         else
         {
             return  true ;
         }
     }
};
2 、别人的程序
运行时间 6ms
class  Solution
{
     public :
     string  longestPalindrome ( string  s )
     {
         if ( s . empty ())  return  "" ;
         if ( s . size ()  ==  1 )  return  s ;
         int  min_start  =  0 ,  max_len  =  1 ;
         for ( int  i  =  0 ;  i  <  s . size ();)
         {
             if ( s . size ()  -  i  <=  max_len  /  2 )  break ;
             int  j  =  i ,  k  =  i ;
             while ( k  <  s . size ()  -  1  &&  s [ k  +  1 ]  ==  s [ k ])  ++ k ;  // Skip duplicate characters.
             i  =  k  +  1 ;
             while ( k  <  s . size ()  -  1  &&  j  >  0  &&  s [ k  +  1 ]  ==  s [ j  -  1 ])  {  ++ k ;  -- j ;  }  // Expand.
             int  new_len  =  k  -  j  +  1 ;
             if ( new_len  >  max_len )  {  min_start  =  j ;  max_len  =  new_len ;  }
         }
         return  s . substr ( min_start ,  max_len );
     }
};
string  longestPalindrome ( string  s )
{
     if ( s . length ()  ==  0  ||  s . length ()  ==  1 ) return  s ;
     string  max ( "" );
     for ( int  i  =  0 ;  i  <  int ( s . length ())  -  1 ;  i ++)
     {
         string  first  =  helper ( s ,  i ,  i );  // The center is s[i]
         if ( first . length ()  >  max . length ()) max  =  first ;
         string  second  =  helper ( s ,  i ,  i  +  1 );  // The center is s[i][i]
         if ( second . length ()  >  max . length ()) max  =  second ;
     }
     return  max ;
}
string  helper ( string  s ,  int  left ,  int  right )
{
     while ( left  >=  0  &&  right  < int ( s . length ())  &&  s [ right ]  ==  s [ left ])
     {
         left --;
         right ++;
     }
     return  s . substr ( left  +  1 ,  right  -  1  -  left );
}
Manacher’s Algorithm( 马拉车算法 )
class  Solution
{
     public :
     // Transform S into T.
     // For example, S = "abba", T = "^#a#b#b#a#$".
     // ^ and $ signs are sentinels appended to each end to avoid bounds checking
     string  preProcess ( const  string &  s )
     {
         int  n  =  s . length ();
         3.5  Longest Palindromic Substring  65
             if ( n  ==  0 )  return  "^$" ;
         string  ret  =  "^" ;
         for ( int  i  =  0 ;  i  <  n ;  i ++)  ret  +=  "#"  +  s . substr ( i ,  1 );
         ret  +=  "#$" ;
         return  ret ;
     }
     string  longestPalindrome ( string  s )
     {
         string  T  =  preProcess ( s );
         const  int  n  =  T . length ();
         int  P [ n ];
         int  C  =  0 ,  R  =  0 ;
         for ( int  i  =  1 ;  i  <  n  -  1 ;  i ++)
         {
             int  i_mirror  =  2  *  C  -  i ;  // equals to i' = C - (i-C)
             P [ i ]  =  ( R  >  i )  ?  min ( R  -  i ,  P [ i_mirror ])  :  0 ;
             // Attempt to expand palindrome centered at i
             while ( T [ i  +  1  +  P [ i ]]  ==  T [ i  -  1  -  P [ i ]])
                 P [ i ]++;
             // If palindrome centered at i expand past R,
             // adjust center based on expanded palindrome.
             if ( i  +  P [ i ]  >  R )
             {
                 C  =  i ;
                 R  =  i  +  P [ i ];
             }
         }
         // Find the maximum element in P.
         int  max_len  =  0 ;
         int  center_index  =  0 ;
         for ( int  i  =  1 ;  i  <  n  -  1 ;  i ++)
         {
             if ( P [ i ]  >  max_len )
             {
                 max_len  =  P [ i ];
                 center_index  =  i ;
             }
         }
         return  s . substr (( center_index  -  1  -  max_len )  /  2 ,  max_len );
     }
};
还有相应的 DP 解法,不在一一收集。
有兴趣的可以看看,
可能需要权限。完成这个题目,就可以解锁。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值