算法分析
区间dp
从当前样子变成初始状态需要添加叶子的数量 等价于 当前样子变成最大的回文串需要剪去的叶子的数量
即至少脱落多少个种子 等价于 总数量 - 最大回文子序列的长度
状态计算的选择方式和最长公共子序列类似
时间复杂度 $O(n^2)$
参考文献
蓝桥杯辅导课
Java 代码
import java.util.Scanner;
public class Main {
static int N = 1010;
static int[][] f = new int[N][N];
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String s = scan.next();
int n = s.length();
for(int len = 1;len <= n;len ++)
{
for(int i = 0;i + len - 1 < n;i ++)
{
int j = i + len - 1;
if(len == 1) f[i][j] = 1;
else
{
f[i][j] = Math.max(f[i][j - 1], f[i + 1][j]);
if(s.charAt(i) == s.charAt(j)) f[i][j] = Math.max(f[i][j], f[i + 1][j - 1] + 2);
}
}
}
System.out.println(n - f[0][n - 1]);
}
}
从当前样子变成初始状态需要添加叶子的数量 等价于 当前样子变成最大的回文串需要剪去的叶子的数量
吊
为啥这一题不用枚举分割点k啊
状态划分依据不同。石子合并是因为最后一步的状态划分为分割点的位置,而这道题状态划分在于从区间l到r,端点选与不选,没法以分割点为状态划分的依据。
石子合并枚举分割点k是为了决策合并的最优方案,可以反问一下,这题枚举分割点干嘛捏?
为什么要这样间接求呢?如果f[i][j]表示是使s[i]~s[j]变成回文串的最少添加字符数,可以求?
应该可以求
我去 确实可以这样 而且很容易搞
加入原本的字符串是abcba,现在给的样例是bc,这不就添加不回去了嘛
妙啊
这里的子序列是不是可以不连续?
66666
666
感觉y总视频题目表述有点多此一举,明明题意是要删除多少个字母变成回文串,却要说题意是要增加多少个字母变成回文串。然后说等价于删除多少个字母变成回文串。。。
卧槽…我没看y总视频但是我也看成要增加字母的意思了.
请问题意怎么理解成要删除多少个字母变成回文串的,我有点绕不过来
就比如ABCBAD变为镜像串,脱落D就可以了,其实就是删除字符D的意思把
可是我觉得这个题意应该是原来的镜像串已经脱离成现在的样子了,应该问加多少个恢复原样。
然后再转化成子序列,也不知道我这个想法对不对,想了好久才明白
- 首先这题可以转换成求最长回文子序列
1. 转换成最长回文子序列
2. 不在最长回文子序列的字母,只要按位置对应添加
3. 即可恢复成最初状态
4. 因此总长度-最长回文子序列的长度就是恢复原回文子序列的长度
再看一遍好像你的理解是正确的,我理解错了
是的哈哈
废物
这咋还骂人呢
菜就多练,实力说话