最长回文子序列和最长回文子序列

最长回文子序列

给定一个字符串 s ,找到其中最长的回文子序列,并返回该序列的长度。可以假设 s 的最大长度为 1000 。

示例 1:
输入:

“bbbab”

输出:

4

一个可能的最长回文子序列为 “bbbb”。

解法:(参考)
与最长回文子串类似,都是从对角线往右上角更新。但是子序列可以不连续,所以递推公式是:
当子序列的首位相等时->dp[i][j] = dp[i+1][j-1] + 2;
当子序列的首位不同时->dp[i][j] = max(dp[i][j-1],dp[i+1][j]);
i为子序列的首部,j为子序列的尾部。

class Solution {
public:
    int longestPalindromeSubseq(string s) {
        if(s.empty())
            return 0;
        int len = s.size();
        vector<vector<int>> dp(len,vector<int>(len,0));
        for(int i=0;i<len;i++){
            dp[i][i] = 1;
        }
        // l表示从i向后移动的位置也就是长度减一,i是起始坐标,j是结束位置坐标
        for(int l=1;l<len;l++){
            for(int i=0;l+i<len;i++){
                int j = l+i;
                if(s[i] == s[i+l]){
                    dp[i][j] = dp[i+1][j-1] + 2;
                } else{
                    dp[i][j] = max(dp[i][j-1],dp[i+1][j]);
                }
            }
        }
        return dp[0][len-1];
    }
};

每一轮循环得到一斜行,最终右上角的值就是最大值。
在这里插入图片描述


最大回文子串

Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.

Example 1:

Input: "babad"
Output: "bab"
Note: "aba" is also a valid answer.

Example 2:

Input: "cbbd"
Output: "bb"

solution:第一次还是先想到的是暴力法(没有通过时间的限制),后面又使用了动态规划,但是运行时间不是很理想,有待改进

动态规划步骤:

矩阵DP初始值都为0

首先是初始化(对角线NP[i][i]上都设置为1,以对角线上的元素为中心的回文长度都为奇数;有两辆相同的将对应的DP[i+1][i]
元素设置为1,以此两元素为中心的回文长度均为偶数)—>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ruuvgKCW-1600589113750)(https://github.com/githublss/image/blob/master/leetimage/first.png)]

然后是在初始化的基础上进行寻找—>

首先假设回文的长度为3,之后依次递增。如果中心的两侧的两个字符是相同的,将其规划进来,将DP中的对应位置设置为1,在进行的过程中用到了前面的结果,一定程度上提高了效率。

class Solution(object):
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        # 暴力法,总是最先想到的
        # def isRevrse(s):
        #     if(s==s[::-1]):
        #         return True
        #     else:
        #         return False
        # maxlen = 0
        # maxi = 0
        # for i in range(len(s)):
        #     for j in range(len(s)-i+1):
        #         if(isRevrse(s[i:i+j]) & (j > maxlen)):
        #             maxlen = j
        #             maxi = i
        # return s[maxi:maxi+maxlen]
        ### 动态规划一
        dp=[[0 for i in range(len(s))] for j in range(len(s))]
        maxLen = 1
        left = 0
        for i in range(len(s)): #初始化
            dp[i][i]=1
            left = i
        for i in range(len(s)-1): #初始化
            if s[i]==s[i+1]:
                dp[i][i+1]=1
                left = i
                maxLen = 2
        for l in range(3,len(s)+1,1):     # l表示当前要检测的字串串的长度
            for i in range(0,len(s)-l+1,1):  # i表示当前要检测的字符串的起始位置
                j = i + l -1                 # j表示当前要检测的字符串的尾位置
                if (dp[i+1][j-1]==1 and s[i]==s[j]):
                    dp[i][j] = 1
                    left = i
                    maxLen = l
        return s[left:left+maxLen]

c++解法:

class Solution {
public:
    string longestPalindrome(string s) {
        if(s.empty())
            return "";
        int len = s.size();
        vector<vector<int>> dp(len,vector<int>(len,0));
        for(int i=0;i<len;i++){
            dp[i][i] = 1;
        }
        int left = 0;
        int maxLen = 1;
        for(int i=0;i<len-1;i++){
            if(s[i] == s[i+1]){
                dp[i][i+1] = 1;
                left = i;
                maxLen = 2;
            }
        }
        // 注意长度是小于等于len,i是子串的起始,j是子串的结尾。
        for(int l=3;l<=len;l++){
            for(int i=0;i<=len-l;i++){
                int j = i+l-1;
                if(s[i] == s[j] && dp[i+1][j-1] == 1){
                    dp[i][j] = 1;
                    left = i;
                    maxLen = l;
                }
            }
        }
        return s.substr(left,maxLen);
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值