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;

}

你可能感兴趣的:(substring)