题目链接:uva 1351 - String Compression
题目大意:给出一个字符串,如果相邻的m个连续子串相等的为s0话,可以将该段表示为m(s0),问说最短需要几个字符可以表示所给字符串。
解题思路:首先要注意(1)m可能是两位数三位数等等;(2)左右括号各算一个字符;(3)s0可以为简化过的字符串,例如s0中包含了一个k(s1)。
然后是dp[i][j]表示的是从i到j的最少字符数,若不考虑i~j这段字符串可以被简化,那么dp[i][j] = min{ dp[i][k] + dp[k+1][j] },但是i~j字符串可以被简化的情况也要考虑,枚举s0的长度,然后去进行判断,是否满足题目要求,满足要求的要维护dp[i][j]最小值dp[i][j] = min(dp[i][j], dp[i][i+k-1] + 2 + catnum((j-i+1)/k));
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; const int N = 205; const int INF = 0x3f3f3f3f; int dp[N][N]; char str[N]; bool judge(int l, int r, int k) { if ((r-l+1)%k) return false; for (int i = 0; i < k; i++) { for (int j = l+i+k; j <= r; j += k) if (str[l+i] != str[j]) return false; } return true; } int catnum(int x) { int ans = 0; while (x) { ans++; x /= 10; } return ans; } int solve () { scanf("%s", str+1); int n = strlen(str+1); memset(dp, INF, sizeof(dp)); for (int i = 0; i <= n; i++) dp[i][i] = 1; for (int i = n; i; i--) { for (int j = i; j <= n; j++) { for (int k = i; k < j; k++) dp[i][j] = min(dp[i][j], dp[i][k] + dp[k+1][j]); int t = j - i + 1; for (int k = 1; k < t; k++) if (judge(i, j, k)) { dp[i][j] = min(dp[i][j], dp[i][i+k-1] + 2 + catnum(t/k)); } } } return dp[1][n]; } int main () { int cas; scanf("%d", &cas); while (cas--) { printf("%d\n", solve()); } return 0; }
uva 1351 - String Compression(dp)
原文:http://blog.csdn.net/keshuai19940722/article/details/19768623