1090: [SCOI2003]字串摺疊
阿新 • • 發佈:2018-11-27
摺疊的定義如下: 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 之間的摺疊成最小的長度。
首先我們要判斷是不是有摺疊的。
如果有,判斷摺疊多少次,因為是有數字在裡面的。要計算數字的位數。
如果不能摺疊,有列舉 k 的位置,然後用區間動規做出來。
#include<bits/stdc++.h> using namespace std; char s[200]; int tot; int f[200][200]; bool check(int x, int y,int z){ if ((y - x + 1) % (z - x +1)) return 0; //是夠整除。 for (int i = x; i <= y; i++) if (s[i] != s[(i-x)%(z-x+1) + x]) return 0; //判斷是不是重複的, int tt = (y - x + 1) / (z - x + 1); //有多少個重複的。 tot = 0; while(tt){ //判斷有幾位數。 tt /= 10; tot++; } return 1; } int main(){ int n; scanf("%s",s); n = strlen(s); for (int i = 0; i < n; i++) f[i][i] = 1; for (int len = 2; len <= n; len++){ for (int i = 0; i <= n - len; i++){ int j = i + len - 1; f[i][j] = len; //初始化。 for (int k = i; k < j; k++){ if (check(i,j,k)) f[i][j] = min(f[i][j],f[i][k] + 2 + tot); //如果重複。 f[i][j] = min(f[i][j], f[i][k] + f[k+1][j]); //不重複,直接加起來。 } } } printf("%d\n",f[0][n-1]); return 0; }