leetcode 516 最长回文子序列 dp 思维

题目要找一个字符串数组中最长的回文子序列,首先如果定义传统的dp[i]
表示0到i最长的回文子序列,则要求的结果是dp[len-1],但是由0到i-1推得i就显得不太容易了,因为我们不知道i要放到前面的哪个最长回文子序列里,这个可以通过枚举小于i的j,但是对于能不能放就麻烦了,因为放进一个i还要构成一个回文,这就要和回文的第一个字符作判断,而这种dp定义是没法判断的。第二种定义,定义dp[i]为,以第i个字符结尾的最长回文子序列,则同样遇到第i个字符与前面的到底能不能构成回文这个问题,也要考虑回文的第一个字符。自然想到了定义dp[i][j]为i到j的最长回文子序列,如果s[i]==s[j],则dp[i][j]=dp[i+1][j-1]+2,如果s[i]!=s[j],dp[i][j]=max(dp[i+1][j],dp[i][j-1]),而我们这个dp只用到了上三角矩阵,所以下三角矩阵式空着的。对于i等于j的情形dp值就为1,对于j等于i+1的情形,如果s[i]和s[j]相等,则dp为2,否则为1,如果下三角矩阵初始化为0,则以上两种可以放到dp递推式中。这个dp中要注意,递推要从底部向上推
因为子问题是从dp[5][5],dp[4][4],dp[4][5]这样子开始的

int longestPalindromeSubseq(char * s){
     int len=strlen(s);
     int dp[len][len];
     for(int i=len-1;i>=0;i--)
     {
         for(int j=i;j<len;j++)
         {
             if(j==i)
             dp[i][j]=1;
             else if(j-i==1)
             {
               if(s[i]==s[j])
               {
                   dp[i][j]=2;
               }
               else
               {
                   dp[i][j]=1;
               }
             }
             else
             {
             if(s[i]==s[j])
             {
                 dp[i][j]=dp[i+1][j-1]+2;
             }
             else
             {
                 dp[i][j]=dp[i+1][j]>dp[i][j-1]?dp[i+1][j]:dp[i][j-1];
             }
             }

         }
     }
     return dp[0][len-1];
}

然后评论区里还有将这个字符串倒置,求最长公共子序列的做法
然后 也可以进行空间的优化,因为上一行的结果只用到了下一行的结果

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值