标签:dp
ababcd letsgogogo nowletsgogogoletsgogogoandrunrunrun
6 9 24
题意:给出一个长度不超过200的字符串,把这个字符串按照一定规则压缩,即可以把几个连续的相同子串压缩成一个串,例如可以把letsgogogo压缩为lets3(go),压缩后的子串如果还可以继续压缩,则可以继续压缩,如可以将nowletsgogogoletsgogogoandrunrunrun压缩为now2(lets3(go))and3(run)。问经过压缩后这个字符串的最短长度是多少。
分析: 区间DP,dp[i][j]表示从i到j的字符串表示的最短长度。
dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j])。注意如果是数字,要用数字的位数表示增加的个数,而不是单纯的增加1.
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 210;
#define INF 0x3fffffff
char str[N];
int n, dp[N][N];
int digit_cnt(int x)
{
int a = 0;
while(x) {
a++;
x /= 10;
}
return a;
}
bool check(int l, int r, int len)
{
if((r - l + 1) % len) return false;
for(int i = l; i < l + len; i++) {
for(int j = i + len; j <= r; j += len)
if(str[i] != str[j]) return false;
}
return true;
}
int get_ans()
{
int i, j, k;
n = strlen(str+1);
for(i = 1; i <= n; i++) dp[i][i] = 1;
for(i = n - 1; i >= 1; i--) {
for(j = i + 1; j <= n; j++) {
dp[i][j] = INF;
for(k = i; k < j; k++)
dp[i][j] = min(dp[i][j], dp[i][k] + dp[k+1][j]);
for(int len = 1; len <= j-i+1; len++) {
if(check(i, j, len)) {
dp[i][j] = min(dp[i][j], dp[i][i+len-1] + 2 + digit_cnt((j - i + 1) / len));
}
}
}
}
return dp[1][n];
}
int main()
{
while(~scanf("%s", str+1)) {
printf("%d\n", get_ans());
}
return 0;
}NYOJ 1067 Compress String(区间dp),布布扣,bubuko.com
NYOJ 1067 Compress String(区间dp)
标签:dp
原文地址:http://blog.csdn.net/lyhvoyage/article/details/38455687