[Luogu P4302] [BZOJ 1090] [SCOI2003]字串摺疊
阿新 • • 發佈:2018-12-15
洛谷傳送門
題目描述
摺疊的定義如下:
-
一個字串可以看成它自身的摺疊。記作
-
是個連線在一起的串的摺疊。記作。
-
如果,則 例如,因為,所以,而
給一個字串,求它的最短折疊。例如的最短折疊為:。
輸入輸出格式
輸入格式:
僅一行,即字串,長度保證不超過。
輸出格式:
僅一行,即最短的摺疊長度。
輸入輸出樣例
輸入樣例#1:
NEERCYESYESYESNEERCYESYESYES
輸出樣例#1:
14
說明
一個最短的摺疊為:
解題分析
區間, 大力判是否相同再轉移即可。
複雜度? 似乎是卡不滿的。
程式碼如下:
#include <cstdio>
#include <cstring>
#include <cctype>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#define R register
#define IN inline
#define W while
#define gc getchar()
#define MX 105
int dp[MX][MX];
char buf[MX];
int len, ans;
IN bool judge(R int x1, R int y1, R int x2, R int y2)
{
if(y1 - x1 > y2 - x2) return false;
if((y2 - x1 + 1) % (y1 - x1 + 1)) return false;
int len = y1 - x1 + 1;
for (R int i = x2; i <= y2; ++i)
if(buf[i] ^ buf[i - len]) return false;
return true;
}
IN int get (R int now)
{
R int ret = 0;
W (now) ++ret, now /= 10;
return ret;
}
int main(void)
{
scanf("%s", buf + 1);
len = std::strlen(buf + 1);
for (R int i = 1; i <= len; ++i)
for (R int j = i; j <= len; ++j)
dp[i][j] = j - i + 1;
for (R int i = 1; i < len; ++i)
{
for (R int j = 1; j <= len - i; ++j)
{
for (R int k = j; k < j + i; ++k)
{
if(!judge(j, k, k + 1, j + i)) dp[j][j + i] = std::min(dp[j][j + i], dp[j][k] + dp[k + 1][j + i]);
else dp[j][j + i] = std::min(dp[j][j + i], dp[j][k] + get((i + 1) / (k - j + 1)) + 2);
}
}
}
printf("%d", dp[1][len]);
}