Problem
Bill tried to compactly represent uppercase character sequence from "A" to "Z" folded by repeating sequences therein.
For example, a sequence showing a method is AAAAAAAAAABABABCCD 10 (A) 2 (BA) B2 (C) D. He formally defined folding sequence of characters and converting them to expand in the following ways: comprising from "A" to a sequence "Z" single character sequence is considered to be folded. Expand this sequence produces the same sequence of individual characters themselves. If the sequence S and Q is folded, the folding sequence is SQ. If S to expand S 'and Q to expand Q', to expand the SQ S'Q '.
If S is a folded sequence, X (S) is folded sequence, wherein X is an integer greater than 1 indicates a decimal. If the expanded S S ', then X (S) to expand S' is repeated X times.
According to this definition, it is easy to expand any given sequence of folding. However, Bill is more interested in the reverse transformation. He desired folded in a given sequence, such that the folded sequence obtained comprises as little as possible the number of characters.
Dolution
We set represents minimum number of characters, set up represents resentment.
Obviously for the interval answer must be divided into two parts:
- Transferred from the sub-intervals; i.e. the sum of the two sub-sections can be obtained:
- Merge all the individual section cycle. At this festival cycle of violence can find.
NUM represents the number of cycles section, minlen represents the minimum cycle length of the section. - at this time
This question is for our enlightenment is not necessarily objectionable DP output recursive lookups done later, when you can not answer sequence by doing record.
code show as below:
#include <bits/stdc++.h>
using namespace std;
const int N = 200;
char a[N];
string g[N][N], t[N][N];
int f[N][N], c[N][N], pre[N][N], n;
int find(int l, int r)
{
for (int L=1;L<=r-l+1;++L)
{
if ((r-l+1) % L) continue;
int flag = 1;
for (int i=l;i<=r-L;++i)
if (a[i] ^ a[i+L]) {
flag = 0;
break;
}
if (flag == 1) return L;
}
return 0;
}
//寻找最小循环节
string str(int x)
{
int t = 0;
int s[1000];
string S;
while (x > 0) s[++t] = x%10, x /= 10;
for (int i=t;i;--i) S += s[i]+'0';
return S;
}
int main(void)
{
freopen("folding.in","r",stdin);
freopen("folding.out","w",stdout);
cin >> a+1;
n = strlen(a+1);
for (int i=1;i<=n;++i) {
f[i][i] = 1;
g[i][i] = a[i];
}
for (int len=2;len<=n;++len)
for (int i=1;i<=n-len+1;++i)
{
int j = i+len-1;f[i][j] = INT_MAX;
for (int k=i;k<j;++k)
if (g[i][k].size() + g[k+1][j].size() < f[i][j])
f[i][j] = g[i][k].size() + g[k+1][j].size(),
g[i][j] = g[i][k] + g[k+1][j];
int len = find(i, j);
if (len == 0) continue;
int num = (j-i+1) / len;
string S = str(num) + '(' + g[i][i+len-1] + ')';
if (S.size() < f[i][j])
f[i][j] = S.size(), g[i][j] = S;
}
cout<<g[1][n]<<endl;
return 0;
}