Problem Specification Value
Time Limit 10 Sec
Memory Limit 162 MB
Submit 1028
Solved 666

Description

折叠的定义如下: 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))

Source


又是一道区间 DP 问题.

考虑每一个区间的折叠的最佳结果, 复杂度应该不超过 O (n^3).

记得记忆化搜索~



#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>

using namespace std;
const int maxn = 200;

char str[maxn];
bool dp_done[maxn][maxn];
int  dp_data[maxn][maxn];

// This function judges whether str[cl, cr] can be repeated in str[l, r] as a
// subset. Exempli gratis:
//     str = "ABCABCABCABC",
//     l = 3, r = 11 -> "ABCABCABC"
//     cl = 3, r = 5 -> "ABC",
// Then it should return true and vice versa.
bool judge_repeatable(int l, int r, int cl, int cr)
{
    // Should the string be indivisible, return false.
    if ((r - l + 1) % (cr - cl + 1) != 0)
        return false;
    // Check if this repetition is correct throughout all characters.
    for (int i = l; i <= r; i++)
        if (str[i] != str[(i - l) % (cr - cl + 1) + cl])
            return false;
    // Therefore this is correct.
    return true;
}

// This gets the digits of number x in decimal.
int get_digits(int x)
{
    int dig = 0;
    while (x > 0) {
        x /= 10;
        dig++;
    }
    return dig;
}

// The core dynamic programming function of this program.
int dp(int l, int r)
{
    // We assure this is sustaining.
    if (l == r)
        return 1;
    // Memorized searching.
    if (dp_done[l][r])
        return dp_data[l][r];
    // Prevent further, useless iterations.
    dp_done[l][r] = true;
    // deflated_min is the minimum length of the deflated string, which strictly
    // is smaller or equal to the length of this substring passed into this
    // function.
    int deflated_min = r - l + 1;
    // Scan for all substrings for potential deflation, as though this substring
    // is repeated throughout the following remainder of substrings.
    for (int i = l; i < r; i++) {
        // Split the string at this position.
        deflated_min = min(deflated_min, dp(l, i) + dp(i + 1, r));
        // If this string is repeatable, then attempt to repeat this string.
        if (judge_repeatable(i + 1, r, l, i))
            deflated_min = min(deflated_min, dp(l, i) + 2 + get_digits((r - i) / (i - l + 1) + 1));
    }
    // Save data for memorized searching.
    dp_data[l][r] = deflated_min;
    return deflated_min;
}

int main(int argc, char** argv)
{
    scanf("%s", str);
    int res = dp(0, strlen(str) - 1);
    printf("%d\n", res);
    return 0;
}