题意:给出一个由大写字母组成的长度为n(1<=n<=100)的串,“折叠”成一个尽量短的串。折叠可以嵌套。多解时可输出任意解。

分析:

1、dp[l][r]为l~r区间可折叠成的最短串的长度。

2、ans[l][r]为l~r区间可折叠成的最短串。

3、先判断当前研究的串是否能折叠,若不能折叠,再枚举分割线,折叠分隔后可折叠的串,以使处理后的串最短。

#pragma comment(linker, "/STACK:102400000, 102400000")
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<iostream>
#include<sstream>
#include<iterator>
#include<algorithm>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<stack>
#include<deque>
#include<queue>
#include<list>
#define Min(a, b) ((a < b) ? a : b)
#define Max(a, b) ((a < b) ? b : a)
const double eps = 1e-8;
inline int dcmp(double a, double b){
if(fabs(a - b) < eps) return 0;
return a > b ? 1 : -1;
}
typedef long long LL;
typedef unsigned long long ULL;
const int INT_INF = 0x3f3f3f3f;
const int INT_M_INF = 0x7f7f7f7f;
const LL LL_INF = 0x3f3f3f3f3f3f3f3f;
const LL LL_M_INF = 0x7f7f7f7f7f7f7f7f;
const int dr[] = {0, 0, -1, 1, -1, -1, 1, 1};
const int dc[] = {-1, 1, 0, 0, -1, 1, -1, 1};
const int MOD = 1e9 + 7;
const double pi = acos(-1.0);
const int MAXN = 100 + 10;
const int MAXT = 10000 + 10;
using namespace std;
string s;
string ans[MAXN][MAXN];
int dp[MAXN][MAXN];
int dfs(int l, int r){
if(dp[l][r] != -1) return dp[l][r];
int len = r - l + 1;
if(len == 1){//串的长度为1,不能折叠也不能枚举分割线
ans[l][r] = s[l];
return dp[l][r] = 1;
}
ans[l][r] = s.substr(l, len);
int tmp = len;//以下判断串是否能折叠
for(int i = 1; i <= len / 2; ++i){//枚举循环周期的长度
if(len % i) continue;
bool ok = true;
for(int j = l + i; j <= r; j += i){//判断串是否以周期为i循环
for(int k = 0; k < i; ++k){
if(s[l + k] != s[j + k]){
ok = false;
break;
}
}
if(!ok) break;
}
if(ok){//该串可以按周期为i折叠
char t[10];
sprintf(t, "%d", len / i);//循环串的长度
dfs(l, l + i - 1);//循环串自身可能是可折叠的
string str(t);
str += "(" + ans[l][l + i - 1] + ")";
int nowlen = (int)str.size();
if(nowlen < tmp){//若折叠后的长度小于不折叠,则更新ans[l][r]
tmp = nowlen;
ans[l][r] = str;
}
}
}
if(tmp != len) return dp[l][r] = tmp;//如果可折叠
for(int i = l; i < r; ++i){//该串不可折叠,枚举分割线
int x = dfs(l, i);
int y = dfs(i + 1, r);
if(x + y < tmp){
tmp = x + y;
ans[l][r] = ans[l][i] + ans[i + 1][r];
}
}
return dp[l][r] = tmp;
}
int main(){
while(cin >> s){
memset(dp, -1, sizeof dp);
int len = (int)s.size();
dfs(0, len - 1);
printf("%s\n", ans[0][len - 1].c_str());
}
return 0;
}

  

最新文章

  1. 【BZOJ1725】[Usaco2006 Nov]Corn Fields牧场的安排 状压DP
  2. ACM_ICPC hdu-2111(简单贪心算法)
  3. Dx unsupported class file version 52.0
  4. 【Java学习笔记】Map集合的keySet,entrySet,values的用法例子
  5. iOS数组使用
  6. 对ArrayList 进行深拷贝
  7. Free Editor
  8. Red5 配置RTMPT
  9. form与action之setter与getter(转)
  10. NYOJ-915 +-字符串(贪心)
  11. 网页html结构搭建方法总结
  12. @Controller和@RestController源码解析
  13. JavaFX——简单的日记系统
  14. luogu P4482 [BJWC2018] Border 的四种求法 - 后缀数组
  15. Linux系统minicom命令详解
  16. downLoad
  17. Docz 用 MDX 写 React UI 组件文档
  18. 图片缓存:浏览器刷新 和 304 Not Modified 与 If-Modified-Since 及 Cache-Control
  19. java.lang.NoClassDefFoundError: org/apache/commons/io/output/DeferredFileOutputStream
  20. 通过git将本地文件上传到码云的方法

热门文章

  1. oozie的常见错误
  2. Java 将数据写入磁盘并读取磁盘上的文件
  3. BottomTabBar 套用 recycleview出错问题
  4. Mysql多对多关系的查询
  5. NO10 查看Linux操作系统-版本-内核-Linux分区
  6. PATH环境 变量
  7. Ajax学习系列——Ajax介绍及优缺点
  8. 编译Linux
  9. (21)Laplance
  10. jQuery中:first,:first-child,first()的使用区别