LeetCode--5.最长回文子串(Longest Palindromic Substring)

题目描述

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。

示例 1:

输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。

示例 2:

输入: "cbbd"
输出: "bb"

思路

1.暴力法
时间复杂度:O(n^3)(每一轮都是n+到1,类同n ^2,一共需要n轮,故为n ^3)
空间复杂度:O(1)
见代码

class Solution {
    //暴力法
public:
    string longestPalindrome(string s) {
        int max=0;
        string ans="";
        for(int i=0;i<s.length();++i)
            for(int j=i;j<s.length();++j)
                //i为起始位置,j为结尾位置,因为1个字符也为回文串,故结尾位置从i开始
            {//判断该子串是否为回文串
                int begin=i,end=j;
                while(begin<end&&s[begin]==s[end])
                {//若相同,则不断向中间靠近
                    begin++;end--;
                }
                //若为回文串,奇数时,end==begin,偶数时begin>end
                if(begin>=end&&max<j-i+1)
                {
                    max=j-i+1;
                    ans=s.substr(i,j-i+1);
                } 
            }
        return ans;
    }
};

2.动态规划法
时间复杂度为O(n^2)
空间复杂度为O(n^2)

class Solution {
    //动态规划法
public:
    string longestPalindrome(string s) {
        int max=0;
        int start=0;//记录最大子串起始位置
        int n=s.length();
        if(n==0)
            return "";
        bool dp[n][n];
        memset(dp, 0, sizeof(dp));
        for(int j=0;j<n;++j)
            for(int i=0;i<=j;++i)
                //i为起始位置,j为结尾位置,因为1个字符也为回文串,故结尾位置从i开始
            {
                //当为单个或两个字符时,判断s[i]==s[j]是否成立,即可判断是否为回文串
                if(j-i<=1)                
                    dp[i][j]=(s[i]==s[j]);
                else
                {
                    //若大于两个字符,则若d[i+1][j-1]为ture
                    //且s[i]==s[j] 则说明s(i,j)也为回文串                    
                    dp[i][j]=dp[i+1][j-1]&&(s[i]==s[j]);
                }
                if(dp[i][j]&&j-i+1>max)
                {//更新最大值
                    max=j-i+1;
                    start=i;
                }
            }
        return s.substr(start,max);
    }
};

3.中心扩展算法
即从中间,向两端扩展,判断是否为回文段
对字符串的每个位置都判断一次
总共要判断n次,扩展的时候也会遍历次字符串
故时间复杂度为O(n^2),空间复杂度为O(1)

class Solution {
    //中心扩展算法
public:
    string longestPalindrome(string s) {
        int max=0;
        int start=0;//记录最大子串起始位置
        int n=s.length();
        if(n==0)
            return "";
        for(int i=0;i<n;++i)
        {
            int l1=matchLen(s,i,i);//以i为中心的奇数个字符
            int l2=matchLen(s,i,i+1);//以i,i+1为中心的偶数个字符
            int len=l1>l2?l1:l2;
            if(len>max)
            {
                max=len;
                if(len&1==1)//奇数
                start=i-len/2;            
                else    //偶数
                start=i-len/2+1;
            }
        }                            
        return s.substr(start,max);
    }
private:    
        int matchLen(string s,int i,int j)
    {//判断以i,j为中心的字符串是否回文
    //i为起始位置,j为结尾位置,判断s[i]==s[j]是否成立,若成立则扩展到i-1,j+1
        if(j-i==1&&s[i]!=s[j])//若为两个不同的字符,则特殊判断
            return 1;            
        while(i>=0&&j<s.length()&&s[i]==s[j])
        {
            --i;
            ++j;        
        }                                               
            return j-i-1;//j与i已经发生改变,故为-1
    }
};

4.Manacher 算法
Manacher算法的时间复杂度为O(N),(运用已有的信息和对称)具体可参考:
https://www.cnblogs.com/grandyang/p/4475985.html

题目网址及题解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值