Description
折叠的定义如下: 1. 一个字符串可以看成它自身的折叠。记作S S 2. X(S)是X(X>1)个S连接在一起的串的折叠。记作X(S) SSSS…S(X个S)。 3. 如果A A’, BB’,则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。
Input
仅一行,即字符串S,长度保证不超过100。
Output
仅一行,即最短的折叠长度。
区间dp,t[i][j]表示i开头长度为j的串的重复次数,f[i][j]表示i开头长度j的串的最短长度。
#include<cstdio> #include<cstring> char s[105]; int f[105][105]; int t[105][105]; int v[105]; inline void mins(int&a,int b){if(a>b)a=b;} int main(){ for(int i=1;i<10;i++)v[i]=3; for(int i=10;i<100;i++)v[i]=4; v[100]=5; scanf("%s",s); int l=strlen(s); for(int i=0;i<=l;i++) for(int j=1;j<=l;j++)f[i][j]=j; for(int i=1;i<=l;i++){ t[l-i][i]=1; for(int j=i+1;j<=l;j++){ t[l-j][i]=1; bool d=1; for(int k=0;k<i;k++){ if(s[l-j+k]!=s[l-j+i+k]){ d=0; break; } } if(d)t[l-j][i]=t[l-j+i][i]+1; } } for(int i=1;i<=l;i++){ for(int j=2;j<=i;j++){ if(i%j==0){ int c=i/j; for(int k=0;k<l;k++) if(t[k][c]>=j)mins(f[k][i],f[k][c]+v[j]); } } for(int k=0;k<l;k++) for(int a=1;a<i;a++)mins(f[k][i],f[k][a]+f[k+a][i-a]); } printf("%d",f[0][l]); return 0; }