首页 > 代码库 > LeetCode5:Longest Palindromic Substring

LeetCode5: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, and there exists one unique longest palindromic substring.

解题思路:

主要有三种:

第一种:Manacher算法,也是最快的,时间复杂度为O(n)

第二种:DP算法,时间复杂度为O(n*n)

第三种:中心法,时间复杂度为O(n*n)

实现代码:

#include <iostream>
#include <vector>
using namespace std;

/**

Given a string S, find the longest palindromic substring in S. 
You may assume that the maximum length of S is 1000, 
and there exists one unique longest palindromic substring.
*/

class Solution {
public:
    //Manacher算法(O(n))
    string longestPalindrome(string s) {
        string p;
        if(s.empty())
            return p;
        int id = 0;
        int mx = 0;
        //以下对要操作的副本str进行格式化,使得其为奇数 
        string str("^");       
        for(int i = 0; i < s.size(); i++)
        {
            str += "#";
            str += s[i];
        }
        str += "#$";
        vector<int> r(str.size(), 0);
        
        for(int i = 1; i < str.size()-1; i++)
        {
            if(mx > i)
                r[i] = min(r[2*id - i], mx - i);
            else
                r[i] = 1;
            while(str[i+r[i]] == str[i-r[i]])//为了防止越界,str头尾插入了‘^‘和‘$‘字符 
                r[i]++;
            if(r[i] + i > mx)
            {
                mx = r[i] + i;
                id = i;
            }
        }
        
        int maxlen = 0;
        int maxid = 0;
        for(int i = 1; i < str.size()-1; i++)
        {
            if(r[i] > maxlen)
            {
                maxlen = r[i];
                maxid = i;
            }            
        }
        //(maxid-1)/2为原字符串中最长回文字串中心字符位置
        //(maxlen-1)/2为原字符串中最长回文子串半径
        //maxlen-1为原字符串中最长回文字串长度 
        return s.substr((maxid-1)/2 - (maxlen-1)/2, maxlen-1);
   
    }
    
    //DP O(n*n)
    string longestPalindrome2(string s) {
        string p;
        if(s.empty())
            return p;
        int len = s.size();
        vector<vector<bool>> dp(len, vector<bool>(len, false));//dp[i][j]表示i~j的字串是否为回文串 
        int maxstart = 0;
        int maxlen = 1;
        for(int i = 0; i < len-1; i++)
        {
            dp[i][i] = true;
            if(s[i] == s[i+1])
            {
                dp[i][i+1] = true;
                maxstart = i;
                maxlen = 2; 
            }
        }
        
        for(int l = 3; l <= len; l++)
        {
            for(int i = 0; i < len-l+1; i++)
            {
                int j = i+l-1;
                if(s[i] == s[j] && dp[i+1][j-1])
                {
                    dp[i][j] = true;
                    maxstart = i;
                    maxlen = l;
                }

            }
        }
        return s.substr(maxstart, maxlen);

    }

    
    //中心法,以每一个字符作为回文串中心,向两边扩展 
    string longestPalindrome3(string s) {
        string p;
        if(s.empty())
            return p;
        int len = s.size();
        int maxstart = 0;
        int maxlen = 0;
        for(int i = 0; i < len; i++)
        {
            int l = i-1;
            int r = i+1;
            int tmpmax = 1;//已i为中心的回文串:奇数 
            while(l >= 0 && r < len && s[l--] == s[r++])
                tmpmax++;
            if(maxlen < tmpmax*2 -1)
            {
                maxlen = tmpmax*2 -1;
                maxstart = l+1;
            }
            
            int l2 = i;
            int r2 = i+1;
            int tmpmax2 = 0;//已i和i+1为中心的回文串,偶数时 
            while(l2 >= 0 && r2 < len && s[l2--] == s[r2++])
                tmpmax2++;
            
            if(maxlen < tmpmax2*2)
            {
                maxlen = tmpmax2*2;
                maxstart = l2+1;
            } 
 
        }

        return s.substr(maxstart, maxlen);
   
    } 
       
};


int main(void)
{
    string s("abbacdd");
    Solution solution;
    string p = solution.longestPalindrome3(s);
    cout<<p<<endl;
    return 0;
}