【bzoj1090】 [SCOI2003]字符串折叠
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
仅一行,即最短的折叠长度。
Sample Input
NEERCYESYESYESNEERCYESYESYES
Sample Output
14
HINT
一个最短的折叠为:2(NEERC3(YES))
题解
dp[l][r]表示l~r的最短折叠长度
即可推出:dp[l][r]=min(r-l+1,dp[l][k]+dp[k+1][r])l<=k<r
当k+1~r可以由l~k重复得到时还要:dp[l][r]=min(dp[l][r],dp[l][k]+2+calc((r-l+1)/(k-l+1)));//calc用来计算一个十进制数所占位数
答案就是dp[0][len-1];
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstdlib> 6 #include<cstring> 7 #define N 107 8 using namespace std; 9 10 int len; 11 int f[N][N],mark[N][N]; 12 char s[N]; 13 14 bool judge(int l,int r,int hl,int hr) 15 { 16 int mod=(r-l)+1; 17 if ((hr-hl+1)%(r-l+1)!=0) return false; 18 for (int i=0;i<hr-hl+1;i++) 19 if (s[l+i%mod]!=s[hl+i]) return false; 20 return true; 21 } 22 int wei(int x) 23 { 24 int zhi=0; 25 while (x) 26 { 27 zhi++; 28 x/=10; 29 } 30 return zhi; 31 } 32 int dfs(int l,int r) 33 { 34 if (l==r) return 1; 35 if (mark[l][r]) return f[l][r]; 36 mark[l][r]=1; 37 int res=r-l+1; 38 for (int i=l;i<r;i++) 39 { 40 res=min(res,dfs(l,i)+dfs(i+1,r)); 41 if (judge(l,i,i+1,r)) res=min(res,dfs(l,i)+2+wei((r-i)/(i-l+1)+1)); 42 } 43 return f[l][r]=res; 44 } 45 int main() 46 { 47 scanf("%s",s); 48 len=strlen(s); 49 printf("%d ",dfs(0,len-1)); 50 }