首页 > 代码库 > bzoj 1090

bzoj 1090

1090: [SCOI2003]字符串折叠

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 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’, 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))

思路: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 }

 

bzoj 1090