Uva1630 Folding

原题链接:uva 1630 Folding

题目大意

给定一个字符串S,可以将其中一段元素折叠,条件是每段相同并且可以嵌套.例如可以将NEERCYESYESNEERCYESYESYES折叠成2(NEERC3(YES)).要求输出方案.

数据范围:
(1 leq n leq 100)

思路

由于n只有100,而且设计整个区间的操作.比较容易想到区间DP.
状态:(f[l][r])表示区间[l,r]最短可以压缩到多短.
入口:(f[l][r] = r - l + 1)即不压缩,就以自己为最终的答案.
转移:
转移有几种情况,分别考虑一下:

  • 直接将区间划分成两半,从两半各自拼过来.这个时候方程是(f[l][r] = min(f[l][r],f[l][k] + f[k + 1][r])其中(kin [l,r-1]).为什么不是三段四段呢?因为两段就已经包含了继续下分的各种情况了,如果三段是比较短的,那么他必然包含在某个两段里的一个最后的答案.
  • 这个区间是可以拆分的.即存在一个(m)是当前区间长度(len)的因数,并且每一段(m)长度的子串都是完全相同的,这个时候每个循环节的答案就是(f[l][l + m - 1]),而每个循环节要有(len / m)的数字在前面以及一对括号,数字可以预处理出来1~100的位数直接放进去用.总的转移方程就是(f[l][r] = min(f[l][r],f[l][l + m - 1] + numlen(len / m) + 2)
    出口:(f[l][r])

不过这个题还要输出具体方案,那么对照着写一个(res[l][r])记录([l,r])区间能获得的最终的字符串的答案具体是谁就可以了.在转移更新答案的时候把新的答案给构造出来.

代码

#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N = 125;
int numlen[N],f[N][N],n;
bool st[N][N];
string s,res[N][N];
bool check(int l,int r,int m)
{
	for(int i = l;i < l + m;++i)
	{
		for(int j = i;j <= r;j += m)
		{
			if(s[j] != s[i])
				return 0;
		}
	}
	return 1;
}
inline void _ct(int l,int r)
{
	for(int i = l;i <= r;++i)
		res[l][r] += s[i];
}
int main()
{
	ios::sync_with_stdio(0);cin.tie(0);
	while(cin >> s)
	{
		n = s.size();s = "#" + s;
		for(int i = 1;i <= 9;++i)	numlen[i] = 1;
		for(int i = 10;i <= 100;++i)	numlen[i] = 2;
		
		for(int len = 1;len <= n;++len)
		{
			for(int l = 1;l + len - 1 <= n;++l)
			{
				int r = l + len - 1;
				f[l][r] = len;res[l][r] = s.substr(l,len);
				for(int k = l;k < r;++k)	
				{
					if(f[l][r] > f[l][k] + f[k + 1][r])
					{
						f[l][r] = f[l][k] + f[k + 1][r];
						res[l][r] = res[l][k] + res[k + 1][r];
					}
					
				}
				for(int m = 1;m < len;++m)
				{
					if(len % m)	continue;
					if(check(l,r,m))	
					{
						if(f[l][r] > f[l][l + m - 1] + numlen[len / m] + 2)
						{
							f[l][r] = f[l][l + m - 1] + numlen[len / m] + 2;
							res[l][r] = to_string(len / m) + 
							"(" + res[l][l + m - 1] + ")";
						}
					}
						
				}
			}
		}
		cout << res[1][n] << endl;
	}

    return 0;
}
原文地址:https://www.cnblogs.com/HotPants/p/13492401.html