题目描述
折叠的定义如下:
一个字符串可以看成它自身的折叠。记作S = S
X(S)是X(X>1)个S连接在一起的串的折叠。记作X(S) = SSSS…S(X个S)。
如果A = A’, B = B’,则AB = A’B’ 例如,因为3(A) = AAA, 2(B) = BB,所以3(A)C2(B) = AAACBB,而2(3(A)C)2(B) = AAACAAACBB
给一个字符串,求它的最短折叠。例如AAAAAAAAAABABABCCD的最短折叠为:9(A)3(AB)CCD。
输入输出格式
输入格式:
仅一行,即字符串S,长度保证不超过100。
输出格式:
仅一行,即最短的折叠长度。
代码
#include<cstdio>
#include<string>
#include<cstring>
using namespace std;
char s[105];
int len,f[105][105],lst[105][105];
inline int read() {
int ret=0,f=1;char ch=getchar();
for (; !isdigit(ch); ch=getchar()) if (ch=='-') f=-f;
for (; isdigit(ch); ch=getchar()) ret=ret*10+ch-48;
return ret*f;
}
inline bool can(int l1,int r1,int l2,int r2) {
if ((r2-l2+1)%(r1-l1+1)) return 0;
for (int i=l2,j=l1; i<=r2; i++) {
if (s[i]!=s[j]) return 0;
if (++j>r1) j=l1;
}
return 1;
}
inline int calc(int x) {
int ret=1,w=10;
if (x>=w) ret++,w*=10;
return ret;
}
int main() {
scanf("%s",s),len=strlen(s);
for (int i=0; i<len; i++) f[i][i]=1;
for (int l=2; l<=len; l++)
for (int i=0; i<=len-l; i++) {
int j=i+l-1;
f[i][j]=j-i+1;
for (int k=i; k<j; k++) {
if (can(i,k,k+1,j)) f[i][j]=min(f[i][j],f[i][k]+2+calc(l/(k-i+1)));
f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]);
}
}
printf("%d\n",f[0][len-1]);
return 0;
}