bzoj 1090
1090: [SCOI2003]字符串折叠
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1413 Solved: 936
[Submit][Status][Discuss]
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))
思路:f[i][j]表示i到j折叠的最小长度,f[i][j]=min(f[i][j],f[i][k]+f[k+1][j],在i--j如果可折叠的话,那么k+1--j为几倍的i---k,判断下
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 char s[101]; 5 int f[101][101]; 6 bool mark[101][101]; 7 8 9 int get(int x){ 10 int sum=0; 11 while(x){ 12 x/=10;sum++; 13 } 14 return sum; 15 } 16 17 bool hh(int l,int r,int cl,int cr){//l-r之间可以由几个cl-cr得到 18 if((r-l+1)%(cr-cl+1)) return false; 19 int x=cl; 20 for(int i=l;i<=r;i++){ 21 if(s[i]!=s[x++])return false; 22 if(x==cr+1) x=cl; 23 } 24 return true; 25 } 26 27 int dp(int l,int r){ 28 if(l==1&&r==1) return 1; 29 if(mark[l][r]) return f[l][r]; 30 mark[l][r]=1; 31 int t=r-l+1; 32 for(int i=l;i<r;i++){ 33 t=min(t,dp(l,i)+dp(i+1,r)); 34 if(hh(i+1,r,l,i)){//可重复 35 t=min(t,dp(l,i)+2+get((r-i)/(i-l+1)+1)); 36 } 37 } 38 return f[l][r]=t; 39 } 40 int main(){ 41 scanf("%s",s); 42 printf("%d\n",dp(0,strlen(s)-1)); 43 }