【每日一题】3月26日题目精讲 区间dp、最长回文子序列

题号:NC13230

------------------------------------以下是和本题还有点关系的相关知识讲解-----------------------------
首先,我们来复习一下区间dp的经典问题:最长回文子序列(如果你没有学过也不不要紧,我会努力写得容易看懂一些)
——给你一个字符串,求一个最长的回文子序列(可以不连续)。
一般情况下,动态规划的解题步骤是:
第一步:根据原问题和子问题来确定状态(我的dp数组要表示什么东西)
第二步:根据状态确定状态转移方程(递推式,怎样求解dp数组)
第三步:确定要不要优化和编程实现方式
(其实你可以这样理解——第一步是确定“我是谁,我在哪”,第二步是确定“我从哪里来”或者“我到哪里去”,第三步是确定“我怎么去”。)
对于本题来说:
原问题是:给定字符串 的最长回文子序列
子问题其实是把原问题进行分解,缩小范围,往往一个问题的子问题会有很多种表示方法,比如说: 个字符的最长回文子序列, 个字符的最长回文子序列等等等,这个时候要结合题目来看——我们知道回文串是个左右对称的结构,所以一个回文串的增加长度是通过左右两边各加一个相同字母来实现的,所以,我们倾向于把子问题描述成:“字符串 的第 个字符到第 个字符的最长回文子序列长度”,那么我们就用dp数组来表示它—— 为字符串 的第 个字符到第 个字符的最长回文子序列长度。
状态确定之后我们需要来考虑这个状态是怎么来的(怎么来和到哪里去考虑一个就好,过程是对称的)。考虑这个状态是如何得来的时候,只需要考虑最后一步是怎么走的,前面的步骤的包含着之前的状态里面了。
具体到这个题Dp[i][j] 有两种情况:
s[i] == s[j]:这个时候可以把s[i]和s[j]分别加到原来0的回文子序列的两端,也就是 i+1 到 j-1 这个区间的字符构成的最长回文子序列的两端,此时 ;
s[i] != s[j]:那么在 这个区间的最长回文子序列中第 个字符和第 个字符一定不能同时存在,所以是可以扔掉他俩中的某一个的(并不是任意一个),此时
其他的情况都是这两种情况的子情况了所以转移方程就出来啦!

在这个问题看懂之后,我们再来讨论一个最长回文子串问题——给你一个字符串,求一个最长的回文子串(连续)。这个问题有非常优秀的O(n)的manacher算法,但是由于和本题没有关系,我在这里只给大家介绍 的dp(你可以作为一种解决问题的思路去学习它,同时它也可以加深你对区间dp的认识)。
我们可以像上个题一样尝试用 dp[i][j] 为字符串 的第 个字符到第 个字符的最长回文子串长度,这时候我们发现,没有办法转移——因为我们不知道第 个字符和第 个字符的选择状况,所以无法转移(更准确的说,当 dp[i][j]!=j-i+1,即第 个和第 个里面至少有一个没选的时候,区间以外的字符我们就不知道是否能选了。)那怎么办呢?我们可以强行规定 中第 个字符和第 个字符都必须选,换句话说 其实是选完了整个 的区间的,也就是说,dp[i][j] ==j-i+1时,这个区间是个回文串,否则就不是,
这样子的话, 存的其实不是回文子串的长度,而是 这个区间是不是回文子串(1表示是,0表示不是)。
只有满足 且 dp[i+1][j-1]==1, 才能等于1,否则都是0。即如果一个串是回文串,往他两边各加一个相同的字母也是回文串,否则就不是回文串了。

-----------------------------------以下是本题解法的分界线-------------------------------------------------------
那么我们终于可以回到“合并回文子串”这个题,如果我们用表示前一个串(a串)的第 个字符到第 个字符后一个串(b串)的第 个字符到第 个字符能否组成一个回文串的话,有四种可能,四种当中任意一种为真f[i][j][k][l]就是真。
构成的串的两端加上 两个字符:

构成的串的两端加上 两个字符:

构成的串的两端加上 两个字符:

构成的串的两端加上 两个字符:

问题解决,其实我们可以看到,这个朴素的最长回文子串问题并没有实质上的区别,只是首尾两端加字母的选择从原来的一种变成了2*2种。
若是你没有写过区间dp的话,我提醒一点:区间dp要从短区间扩展到长区间,所以如果你不是使用记忆化搜索的话,就需要按区间长短来枚举而不是直接枚举首末端点!
一个小问题可能出现在边界上:的真假性显而易见的等于 的真假性,但是转移过程中有可能找 a/b 串中有一个串一个字符都没有选的情况去转移,这个处理非常简单:只要两个串选中的字符个数等于1,直接f值等于1就好(果选中的字符个数小于1,那已经是非法状态了)
代码可戳我查看~

看完邓老师的题解,记得自己去做题提高呀~
欢迎各位大佬来做题写题解,也欢迎大家踊跃在本讨论贴中提问!

活动奖励:

在牛客博客中写出题解,并回复地址
审核通过可获得10-50牛币(依据题目难度和题解的内容而定)

本道题目4月2日中午12:00之前写的题解有获得牛币资格~

牛客博客开通方式

  1. 如何开通牛客博客:https://www.nowcoder.com/discuss/202952
  2. 如何使用博客搬家功能:进入博客--->设置--->底部博客搬家
  3. 如果你对牛客博客有任何意见或建议:牛客博客意见反馈专贴
全部评论
https://blog.nowcoder.net/n/6a7de4febd824227ad7a32e9f429bcaf
2 回复 分享
发布于 2020-03-25 12:59
https://blog.nowcoder.net/n/91e8be92e24b4b64b57e87dc4041818c
1 回复 分享
发布于 2020-03-25 23:20
https://blog.nowcoder.net/n/0391d35caec24edbbc135cabc7c32880
1 回复 分享
发布于 2020-03-25 22:33
https://blog.nowcoder.net/n/d3d974705356402390628d80232dbe43
1 回复 分享
发布于 2020-03-25 18:10
https://blog.nowcoder.net/n/d46a57a977bd41cba970096ad1205213
1 回复 分享
发布于 2020-03-25 17:47
https://blog.nowcoder.net/n/f426f2aa206f48809d9108a0bc068960
1 回复 分享
发布于 2020-03-25 15:39
https://blog.nowcoder.net/n/ac0dfe48d7f64b2183765128065b4a69
点赞 回复 分享
发布于 2020-05-05 15:07
https://blog.nowcoder.net/n/99e88da2759242ac88e117f7da3ee955 
点赞 回复 分享
发布于 2020-05-05 14:51
https://blog.nowcoder.net/n/1cf8ef4e804341a7b5e702059589d917
点赞 回复 分享
发布于 2020-05-04 22:07
https://blog.nowcoder.net/n/8d2143f1f292423a90e01c9ec4ca08f0 阿青姐,题目数据有锅吗? 这个代码提交只得了90分 https://ac.nowcoder.com/acm/contest/view-submission?submissionId=43650497&returnHomeType=1&uid=386035050 而这份有100分 https://ac.nowcoder.com/acm/contest/view-submission?submissionId=43650500&returnHomeType=1&uid=386035050 但是这两份代码唯一的区别就是下图。按道理来说这两种写法本质一样,不可能存在一种写法过,另外一种写法不过的情况把
点赞 回复 分享
发布于 2020-05-03 10:03
https://blog.nowcoder.net/n/6f36d0f8a47e48d09bc81915af2993cd
点赞 回复 分享
发布于 2020-05-03 00:30
https://blog.nowcoder.net/n/b17f18a9f40a4bd2a4c65b074737b255
点赞 回复 分享
发布于 2020-05-02 14:09
https://blog.nowcoder.net/n/a1d4813a89e14aeda839b2e5028f9a1c
点赞 回复 分享
发布于 2020-05-02 12:06
https://blog.nowcoder.net/n/461d0951a50342bc8a7157a54a24d0e9
点赞 回复 分享
发布于 2020-05-01 12:28
题解中 说在两端加入b[l−1] 这个字符应该是表述错误吧,应该是两端加入b[l]这个字符吧
点赞 回复 分享
发布于 2020-04-09 20:46
https://blog.nowcoder.net/n/f99c8a450db94dfa9378f930a0285d43
点赞 回复 分享
发布于 2020-04-01 18:59
https://blog.nowcoder.net/n/80add740d2154e2fb71eff442e328567
点赞 回复 分享
发布于 2020-03-27 17:40
https://blog.nowcoder.net/n/abb1619c037e4cec8a776e742384040a
点赞 回复 分享
发布于 2020-03-27 12:53
https://blog.nowcoder.net/n/97a18a19049f4883aa7bf0be32b34508
点赞 回复 分享
发布于 2020-03-26 16:45
https://blog.nowcoder.net/n/4e8e219e386040d4bb77d2cd6786f0c5
点赞 回复 分享
发布于 2020-03-26 11:55

相关推荐

06-27 12:54
已编辑
门头沟学院 Java
累了,讲讲我的大学经历吧,目前在家待业。我是一个二本院校软件工程专业。最开始选专业是觉得计算机感兴趣,所以选择了他。本人学习计算机是从大二暑假结束开始的,也就是大三开始。当时每天学习,我个人认为Java以及是我生活的一部分了,就这样持续学习了一年半,来到了大四上学期末,大概是在12月中旬,我终于找的到了一家上海中厂的实习,但我发现实习生的工作很枯燥,公司分配的活也不多,大多时间也是自己在自学。就这样我秋招末才找到实习。时间来到了3月中旬,公司说我可以转正,但是转正工资只有7000,不过很稳定,不加班,双休,因为要回学校参加答辩了,同时当时也是心高气傲,认为可以找到更好的,所以放弃了转正机会,回学校准备论文。准备论文期间就也没有投递简历。然后时间来到了5月中旬,这时春招基本也结束了,然后我开始投递简历,期间只是约到了几家下场面试。工资也只有6-7k,到现在我不知道该怎么办了。已经没有当初学习的心劲了,好累呀,但是又不知道该干什么去。在家就是打游戏,boss简历投一投。每天日重一次。26秋招都说是针对26届的人,25怎么办。我好绝望。要不要参加考公、考研、央国企这些的。有没有大佬可以帮帮我。为什么感觉别人找工作都是顺其自然的事情,我感觉自己每一步都在艰难追赶。八股文背了又忘背了又忘,我每次都花很长时间去理解他,可是现在感觉八股、项目都忘完了。真的已经没有力气再去学习了。图片是我的简历,有没有大哥可以指正一下,或者说我应该走哪条路,有点不想在找工作了。
码客明:太累了就休息一下兄弟,人生不会完蛋的
如果实习可以转正,你会不...
点赞 评论 收藏
分享
06-08 22:25
门头沟学院 Java
从零开始的转码生活:这hr不会打开手机不分青红皂白给所有人群发这句话,过一会再给所有人再发一遍,这肯定会有重复的,不管,再过一会再发一遍
点赞 评论 收藏
分享
评论
15
6
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务