刷LeetCode(5)——Longest Palindromic Substring

刷LeetCode(5)——Longest Palindromic Substring

Code it now! https://leetcode.com/problems/longest-palindromic-substring/description/

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

Example:

Input: "babad"

Output: "bab"

Note: "aba" is also a valid answer.

Example:

Input: "cbbd"

Output: "bb"

解法一:暴力法
最容易想到的就是暴力破解,求出每一个子串,之后判断是不是回文,找到最长的那个。

求每一个子串时间复杂度O(N^2),判断子串是不是回文O(N),两者是相乘关系,所以时间复杂度为O(N^3)。

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

using namespace std;

class Solution {
public:
    string longestPalindrome(string& str) {
        int start = 0 ,maxLength = 0;

        const int len = str.length();

        for( int i = 0;i<=len-1;i++)
        {
            for( int j=i+1;j<=len;j++)
            {
                if( isPalindromeStr(str,i,j) )
                {

                    if( maxLength < j -i ){
                        maxLength = j - i;
                        start = i;
                    }
                }
            }
        }
        return str.substr(start,maxLength);
    }


    bool isPalindromeStr(string& str,int start,int end)
    {

        const int len = end - start;

        if( len == 1 )
            return true;

        for(int i=start,j=end-1;i<j;i++,j--)
        {
            if( str[i] != str[j] )
                return false;
        }
        return true;
    }
};



int main()
{
    string str;
    vector <string> v;

    while( getline(cin,str) &&  !str.empty() )
    {
        v.push_back(str);
    }

    for( vector<string>::iterator iter = v.begin(); iter != v.end(); ++iter)
    {
        string result = Solution().longestPalindrome(*iter);

        cout<< " result = " << result << endl;
    }
    return 0;
} 

解法二:动态规划
回文串就是正着读和反着读一样的字符串,如“abba”,”abcba”,最长回文子串是字符串的子串中最长的属于回文串的子串。如字符串”abbaabccba”的最长回文子串为”abccba”,本文采用动态规划算法来查找最长回文子串,算法时间复杂度为O(n²)。设状态dp[j][i]表示索引j到索引i的子串是否是回文串。则易得转移方程如下:
图1
则dp[j][i]为true时表示索引j到索引i形成的子串为回文子串,且子串起点索引为i,长度为j+i-1。代码实现如下:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

using namespace std;

class Solution {
public:
    string longestPalindrome(string& str) {
        int start = 0 ,maxLength = 1;

        const int len = str.length();
        vector< vector<int> > vec(len,vector<int>(len,0));

        for( int j = 0;j<len;j++)
        {
            for( int i=0;i<=j;i++)
            {
                if( i == j ||
                    ( j == i+1 && str[i] == str[j] ) ||
                    (j > i + 1 && vec[i+1][j-1]) && str[i] == str[j] )
                {
                    vec[i][j] = 1;

                    if( maxLength < j -i +1 )
                    {
                        maxLength = j -i +1;
                        start = i;
                    }
                }

            }
        }
        return str.substr(start,maxLength);
    }

};



int main()
{
    string str;
    vector <string> v;

    while( getline(cin,str) &&  !str.empty() )
    {
        v.push_back(str);
    }

    for( vector<string>::iterator iter = v.begin(); iter != v.end(); ++iter)
    {
        string result = Solution().longestPalindrome(*iter);

        cout<< " result = " << result << endl;
    }
    return 0;
} 

解法三:中心扩展
中心扩展就是把给定的字符串的每一个字母当做中心,向两边扩展,这样来找最长的子回文串。算法复杂度为O(N^2)。
但是要考虑两种情况:
1、像aba,这样长度为奇数。
2、想abba,这样长度为偶数。

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

using namespace std;

class Solution {
public:
    string longestPalindrome(string& str) {
        int start = 0 ,maxLength = 1;

        const int len = str.length();

        // if the len is odd
        for( int i=0;i<len;i++)
        {
            int left = i - 1;
            int right = i + 1;
            while( left >= 0 && right < len && str.at(left) == str.at(right) ){
                if( maxLength < right - left + 1 ){
                    maxLength = right - left + 1;
                    start = left;
                }
                left--;
                right++;
            }
        }

        // if the len is even 
        for( int i=0;i<len;i++)
        {
            int left = i;
            int right = i + 1;
            while( left >= 0 && right < len && str.at(left) == str.at(right) )
            {
                if( maxLength < right - left + 1 ){
                    maxLength = right - left + 1;
                    start = left;
                }
                left--;
                right++;
            }
        }

        return str.substr(start,maxLength);
    }

};



int main()
{
    string str;
    vector <string> v;

    while( getline(cin,str) &&  !str.empty() )
    {
        v.push_back(str);
    }

    for( vector<string>::iterator iter = v.begin(); iter != v.end(); ++iter)
    {
        string result = Solution().longestPalindrome(*iter);

        cout<< " result = " << result << endl;
    }
    return 0;
} 

解法四:Manacher 算法,参考我另一篇博客—最长回文子串——Manacher 算法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值