1. 程式人生 > >BZOJ1090[SCOI2003] 字串摺疊

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]dp[l][r]表示區間[l,r][l,r]的最短長度,轉移的時候需要列舉分界點合併,同時看一下中間的串能否合併為一個串。

程式碼
#include<bits/stdc++.h>
using namespace std;
const int M=105;
char ch[M];
int dp[M][M];
bool merge(int l1,int r1,int l2,
int r2) { if((r1-l1+1)%(r2-l2+1))return 0; for(int i=l1;i<=r1;++i)if(ch[i]!=ch[(i-l1)%(r2-l2+1)+l2])return 0; return 1; } int lg(int x){int t=0;while(x){x/=10;t++;}return t;} int dfs(int l,int r) { if(l==r)return 1; if(dp[l][r])return dp[l][r]; int ans=r-l+1; for(int i=l;i<r;++i) { ans=min
(ans,dfs(l,i)+dfs(i+1,r)); if(merge(i+1,r,l,i))ans=min(ans,dfs(l,i)+2+lg((r-i)/(i-l+1)+1)); } return dp[l][r]=ans; } void in(){scanf("%s",ch+1);} void ac(){printf("%d",dfs(1,strlen(ch+1)));} int main(){in(),ac();}