刷LeetCode(5)——Longest Palindromic Substring

来源:互联网 发布:林向正手抛网淘宝价格 编辑:程序博客网 时间:2024/06/01 12:36

刷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 算法。

原创粉丝点击