1. 程式人生 > >【bzoj1090】 [SCOI2003]字符串折疊

【bzoj1090】 [SCOI2003]字符串折疊

min pac 在一起 content blog sample clu class 折疊

【bzoj1090】 [SCOI2003]字符串折疊

Description

折疊的定義如下: 1. 一個字符串可以看成它自身的折疊。記作S ? S 2. X(S)是X(X>1)個S連接在一起的串的折疊。記作X(S) ? SSSS…S(X個S)。 3. 如果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。

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\n",dfs(0,len-1)); 50 }

【bzoj1090】 [SCOI2003]字符串折疊