题目描述 给一个由小写字母组成的字符串,我们可以用一种简单的方法来压缩其中的重复信息。压缩后的字符串除了小写字母外还可以(但不必)包含大写字母R与M,其中M标记重复串的开始,R重复从上一个M(如果当前位置左边没有M,则从串的开始算起)开始的解压结果(称为缓冲串)。 bcdcdcdcd可以压缩为bMcdRR,下面是解压缩的过程
另一个例子是abcabcdabcabcdxyxyz可以被压缩为abcRdRMxyRz。
输入
输入仅一行,包含待压缩字符串,仅包含小写字母,长度为n。
输出
输出仅一行,即压缩后字符串的最短长度。
样例输入
bcdcdcdcdxcdcdcdcd
样例输出
12
题解 把题目读懂就挺不容易的。。。考试的时候读了很久的题,很久没做过区间dp,没想到正解。大致写了一下每一位的值可以怎么得到,就被循环节给绕进去了。因为没有细致做这道题,样例也没有手动分析。下午改题之前动手模拟了一个测试点,就对“重复”这个定义的理解深了很多。 f[i][j]表示i之前有一个重复开始,到j的最小长度。 f[i][i]=2;在i之前放置起点 bj(f[i][j],f[i][j-1]+1);确认之前更新的是否最优 bj(f[i][j*2-i+1],f[i][j]+1);如果循环在继续,以i到j为一个循环节更新下一个循环节 f[i][i]=1;起点本身没必要循环 之后再类似弗洛伊德确认各区间最优值bj(f[i][j],f[i][k]+f[k+1][j]); 结果即为f[0][n-1]; 关于dp还是要有更抽象的概念,如果纠结于细节就会越绕越深。要善于抓住问题的关键,列出状态,否则真是没办法做。对于和字符串有关的题一直觉得难做,其实也是因为不擅长把字符转化成数之间的关系。只要找准状态,严格按照状态设计程序,dp应该是有规律可循的。
#include#include #include #include using namespace std;int n,f[55][55];string a;bool d;void bj(int &x,int y){ x=x >a; n=a.size(); for(int i=0;i