bzoj1068 [SCOI2007]压缩

1068: [SCOI2007]压缩


Ti++me Li++mit:1 SecMemory Limit:128 MB
Submit:1574Solved:1004
[Submit][Status][Discuss]

Description

  给一个由小写字母组成的字符串我们可以用一种简单的方法来压缩其中的重复信息。压缩后的字符串除了小
写字母外还可以linux(但不必)包含大写字母R与M其中M标记重复串的开始,R重复从上一个字符串逆序输出M(如果当前includes是什么意思位置左边没
有M,则从串的开始算起)开始的解压结果(称为缓冲串)。 bcdcdlinuxcdcd可以压缩为bMcdRR,下面是解压缩的过程

  另一个例子是abcabincludescdabcabcdxyxyz可以被压缩为abcRdRMxyRz。

Input

  输入仅一包含待压缩字符串,仅包含小写字母,长度为n。

Output

  include翻译输出仅一,即压缩其他综合收益后字符串的最短长度。

Sample Input

bcdcdcdcdxcdcdcdcd

Sample Output

12

HINT

在第一个例子中,解为aaaRa,在第二个例子中,解为bMcdRRxMcdRR。

【限制】

100%的数据满足:1<=n<=50 100%的数据满足:1<=n<=50

分析:挺巧妙的一道题.

   首先可以一其他业务收入眼看出来这其他货币资金是一个区间dp,但是直接想状态以及状态转移方程很难.一般的区间dp状态都表示为f[l][r]表示将区间[l,r]处理递归函数后的最小长其他综合收益属于什么科目度,但在这题里似乎还缺点什么.

   考虑一下搜索.首先需要知道,在串的左侧默认有一个“M”,这是不计入串长的.每次搜区间[l,r]能被压缩成多短.接下来你有几种操include用法作:1.找个位置放R其他. 2.找个位置放M.

   对于第一个操作,如果R放在串的中间正好,那么这个串的长度就缩成了一include是什么意思中文半,可以递归处理下字符串怎么输入去. 如果R放在偏右位置,没有意义.如果R放在偏左位置,那么可以将串一分为二,左边放了R的系统运维面试题及答案部分继续递归,右边就用原串,结束递归. question:为什么在这里不讨论右边放R呢?如果右边放R,那么前其他面必有一个M,这就属于第二个操作了.

   对于第二个操其他货币资金作,找了一个字符串怎么输入位置放M后,可以发现左右两半就是一模一样的子问题了,递归下去.

   可以发现,第二个操作的M对于第一个操作的R是一个制约左右,只有左边放了M才能放R.

   linux系统安装到这里,记忆化搜索include名词一下就可以了.当然,也可以用递推.令f[i][j][0/1]表示区间[l,r]中有没有放M压缩后最短的串. 具体的递推方程看我的代码吧:

#include <cstdio>
#include <cstring>
#include <iostreainclude什么意思m>
#include <algorithm>
using namespace std;
const int inf = 0x7ffffff;
char s[60];
int len,f[60][60][2];
bool check(int x,int y)
{
if ((y - x + 1) & 1)
return false;
int mid = (x + y) >> 1;
for (int i = 1; i <= mid - x + 1; i++)
{
if (s[i + x - 1] != s[mid + i])
return false;
}
return true;
}
int main()
{
scanf("%s",s + 1);
len = strlen(s + 1);
for (int l = 1; l <= len; l++)
{
for (int i = 1; i + l - 1 <= len; i++)
{
int j = i + l - 1;
f[i][j][0] = f[i][j][1] = (j - i + 1);
for (int k = i; k < j; k++)
f[i][j][1] = min(f[i][j][1],min(f[i][k][0],f[i][k][1]) + 1 + min(f[k + 1][j][0],f[k + 1][j][1]));
for (int k = i; k < j; k++)
f[i][j][0] = min(f[i][j][0],f[i][k][0] + j - k);
if (check(i,j))
f[i][j][0] = min(f[i][j][0],f[i][(i + j) >> 1][0] + 1);
}
}
printf("%d\n",min(f[1][len][0],f[1][len][1]));
return 0;
}