腾讯2016软开实习生笔试题-编程2:最大回文子串长度

本文介绍了一种使用带备忘录的递归方法解决最长回文子串问题的C++实现,通过从字符串两端逐步向中间逼近的方式,有效地避免了重复计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

笔试编程第2题是一个字符串题,要求给定字符串最大长度的子串,思路也很明了。我是使用的带备忘录的递归方法(recursion with memoization)。

问题:求给定字符串s的回文(palindrome)子串中,长度最大的回文子串的长度。
回文(palindrome)是指从左往右读和从右往左读字符串,看到的字符串都是一样的。比如“cabbeaf”,回文子串包括”c”“aba”“abba”等,最长的子串是“abba”,长度为4.
程序输入:“cabbeaf”
程序输出:4

// C++ program to find the length of the longest palindrome
// for string "abeba" , longest palindrome is "abeba", thus 5; 
// use recursion with memorization method
#include<algorithm>
#include<iostream>
#include<vector>

using namespace std;

class Solution
{
    // b/e is the begin/end index of the string s
    // dp[i][j] is the biggest length of palindrome of s[i][j]
    int palLength(string s, int b, int e, vector<vector<int>>&dp)
    {
        if (dp[b][e] != 0) return dp[b][e];
        if (b > e ) return 0;
        if (b == e) { dp[b][e] = 1; return 1; }
        //if s[b]=s[e], then move b forward and e backward and do recursion
        if (s[b] == s[e]){
            dp[b][e] = palLength(s, b + 1, e - 1, dp) + 2;
        }
        //else move b forward or e backward and find the bigger one
        else dp[b][e] = std::max(palLength(s, b + 1, e, dp), palLength(s, b, e - 1, dp));
        return dp[b][e];
    }
public:
    int findPalindrome(string s){
        int n = s.size();
        vector<vector<int>> dp(n, vector<int>(n, 0));
        return palLength(s, 0, n - 1, dp);
    }
};

// Driver program to test above function
int main()
{
    string s("cabbeaf");
    Solution solution;
    cout << solution.findPalindrome(s);
}

这道题在leetcode上见过类似的题目,leetcode上是要求所有可能的划分结果最少的划分次数,而这里只用求划分之后的回文子串最长的长度就可以了。
用递归方法的思路是从字符串两头开始找,对于当前头b和当前尾e指定的字符串s[b…e],如果头和尾字符一样s[b]=s[e],那么最大回文子串长度就是s[b+1 … e-1]的最大回文子串长度加上2;如果头和尾字符不一样,那么头和尾各移动一步求回文子串长度,即求s[b+1…e]和s[b…e-1]的回文子串长度,然后s[b…e]的最大回文子串长度就是s[b+1…e]和s[b…e-1]中的最大值。递归结束条件是b>=e,这里有一点注意的就是b>e,则返回0,b=e时按理说应该返回1,因为对于一个字符,本身就可以看作是长度为1的回文。这里根据题目要求来做相应判断就可以了。
另外,为了避免递归做重复的工作,用一个矩阵dp来记录已经求得的部分的回文子串长度,初始dp矩阵的元素都为0,递归程序开始检查dp[b][e]是不是为0,不为0则说明已经找过了,直接返回该值就可以了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值