5最长回文子串

一、前言

标签:动态规划、中心扩散。

问题来源LeetCode 5 难度:中等。

问题链接:https://leetcode-cn.com/problems/longest-palindromic-substring/

 

二、题目

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

示例1:

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

示例2:

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

 

三、思路

两种解题方法。

复杂度分析:时间复杂度 O(n2),空间复杂度O(n2)

方法二:中心扩散

中心点可能是一个也可能是两个,以中心点向两边扩散判断最长的回文串。

 

四、编码实现

//==========================================================================
/*
* @file    : 005_LongestPalindrome.h
* @label   : 动态规划、中心扩散
* @blogs   : https://blog.csdn.net/nie2314550441/article/details/107497550
* @author  : niebingyu
* @date    : 2020/07/20
* @title   : 5.最长回文子串
* @purpose : 给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
*
*
* 示例1:
* 输入: "babad"
* 输出: "bab"
* 注意: "aba" 也是一个有效答案。
*
* 示例 2:
* 输入: "cbbd"
* 输出: "bb"
*
*
* 来源:力扣(LeetCode)
* 难度:中等
* 链接:https://leetcode-cn.com/problems/longest-palindromic-substring/
*/
//==========================================================================
#pragma once
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <assert.h>
using namespace std;

#define NAMESPACE_LONGESTPALINDROME namespace NAME_LONGESTPALINDROME {
#define NAMESPACE_LONGESTPALINDROMEEND }
NAMESPACE_LONGESTPALINDROME

// 方法一,动态规划
// f(i, i) = true
// f(i,j) = f(i+1, j−1) ∧ (Si == Sj)
// 时间复杂度 O(n2), 空间复杂度O(n2)
class Solution_1 
{
public:
    string longestPalindrome(string s) 
    {
        int n = s.size();
        vector<vector<int>> dp(n, vector<int>(n));
        string ans;
        for (int j = 0; j < n; ++j) 
        {
            for (int i = j; i >= 0; --i) 
            {
                if (i == j) 
                    dp[i][j] = 1;
                else if (j - i == 1) 
                    dp[i][j] = (s[i] == s[j]);
                else 
                    dp[i][j] = (s[i] == s[j] && dp[i + 1][j - 1]);
                    
                if (dp[i][j] && j-i+1 > ans.size()) 
                    ans = s.substr(i, j - i + 1);
            }
        }
        return ans;
    }
};

// 方法二,中心扩展
// 时间复杂度 O(n2), 空间复杂度O(1)
class Solution_2
{
public:
    string longestPalindrome(string s) 
    {
        int len = s.size();
        if(len == 0 || len == 1)
            return s;

        int start = 0;//记录回文子串起始位置
        int end = 0;//记录回文子串终止位置
        int mlen = 0;//记录最大回文子串的长度
        for(int i = 0; i < len; i++)
        {
            int len1 = expendaroundcenter(s, i, i); //一个元素为中心
            int len2 = expendaroundcenter(s, i, i + 1); //两个元素为中心
            mlen = max(max(len1, len2), mlen);
            if(mlen > end - start + 1)
            {
                start = i - (mlen - 1) / 2;
                end = i + mlen / 2;
            }
        }

        //该函数的意思是获取从start开始长度为mlen长度的字符串
        return s.substr(start, mlen);
    }

private:
    int expendaroundcenter(string s,int left,int right)
    //计算以left和right为中心的回文串长度
    {
        int L = left;
        int R = right;
        while(L >= 0 && R < s.length() && s[R] == s[L])
        {
            L--; R++;
        }

        return R - L - 1;
    }
};

以下为测试代码//
// 测试 用例 START
void test(const char* testName, string str, string expect)
{
    Solution_2 s;
    string result = s.longestPalindrome(str);

    if (result == expect)
        cout << testName << ", solution passed." << endl;
    else
        cout << testName << ", solution failed. " << endl;
}

// 测试用例
void Test1()
{
    string str = "aa";
    string expect = "aa";
    test("Test1()", str, expect);
}

void Test2()
{
    string str = "abcdcba";
    string expect = "abcdcba";
    test("Test2()", str, expect);
}

void Test3()
{
    string str = "babad";
    string expect = "bab";
    test("Test3()", str, expect);
}

void Test4()
{
    string str = "bananas";
    string expect = "anana";
    test("Test3()", str, expect);
}

void Test5()
{
    string str = "cbbd";
    string expect = "bb";
    test("Test5()", str, expect);
}

NAMESPACE_LONGESTPALINDROMEEND
// 测试 用例 END
//
void LongestPalindrome_Test()
{
    cout << "------ start 5.最长回文子串 ------" << endl;
    NAME_LONGESTPALINDROME::Test1();
    NAME_LONGESTPALINDROME::Test2();
    NAME_LONGESTPALINDROME::Test3();
    NAME_LONGESTPALINDROME::Test4();
    NAME_LONGESTPALINDROME::Test5();
    cout << "------ end 5.最长回文子串 --------" << endl;
}

执行结果:

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值