题目大意:
压缩字符串。
例如
letsgogogo = lets3(go)
letsgogogo的长度是10
lets3(go)的长度是9
3(go)的长度计算:每个字符算1的长度 所以这是5
思路:
字符号DP。
区间DP。
dp[i][j]表示在从i到j可以达到的最短的产地故
代码:
#include <iostream>
using namespace std;
#include <cstring>
#include <stdio.h>
char str[205];
int len;
int dp[205][205];
const int INF = 0x3f3f3f3f;
int judge(int s,int e,int j) {
for(int i = s + j; i <= e; i += j) {
for(int k = 0; k < j ; k++)
if(str[s + k] != str[i + k])
return 0;
}
return (e - s + 1)/j;
}
int getnum(int x) {
if(x >= 0 && x <= 9 )
return 1;
if(x >= 10 && x <= 99)
return 2;
return 3;
}
void solve() {
for(int i = 0; i < len; i++)
dp[i][i] = 1;
int temp;
for(int l = 2; l <= len; l++) {//长度
for(int s = 0; s <= len - l; s++) {//起点
dp[s][s + l - 1] = INF;//s + l - 1是终点
for(int k = s ; k < s + l - 1; k++)
dp[s][s + l - 1] = min(dp[s][s + l - 1],dp[s][k] + dp[k + 1][s + l - 1]);
for(int j = 1; j <= l / 2; j++) {
if(l % j)//如果不是j的倍数的话 那么就不可能有重复的
continue;
temp = judge(s,s + l - 1, j);
if(temp)
dp[s][s + l - 1] = min(dp[s][s + l - 1],dp[s][s + j - 1]+ 2 + getnum(temp));
}
}
}
}
int main() {
int n;
scanf("%d",&n);
for(int i = 0; i < n; i++) {
scanf("%s",str);
len = strlen(str);
solve();
printf("%d\n",dp[0][len - 1]);
}
return 0;
}