zoukankan      html  css  js  c++  java
  • P4302 [SCOI2003]字符串折叠

    我居然在第一个最优解?

    (f_{i,j})([i,j])中的最短长度。

    [f_{i,j} = min(min limits_{i le k < j} {f_{i,k} + f_{k + 1,j}},min limits_{i le k < j \ s[i,k]是s[i,j]的循环节} {f_{i,k} + LEN(L) + 2}) ]

    其中(LEN(x))(x)的位数,(L)为循环节数。

    时间复杂度(O(n ^ 4))?显然不是。

    (s[i,k])的长度不整除(s[i,j])的长度时,显然不成立,剪枝。

    #include <bits/stdc++.h>
    using namespace std;
    const int inf = 0x3f3f3f3f;
    const int N = 110;
    char s[N];
    int f[N][N];
    int n;
    
    int check(int l, int r, int R)
    {
        int k = l;
        int cnt = 0;
        for (int i = l; i <= R; i++)
        {
            if (k > r)
                k = l, cnt++;
            if (s[k] != s[i])
                return 0;
            ++k;
        }
        return cnt;
    }
    
    int Getlen(int x)
    {
        int cnt = 0;
        while (x)
        {
            cnt++;
            x /= 10;
        }
        return cnt;
    }
    
    int main(void)
    {
        scanf("%s", s + 1);
        n = strlen(s + 1);
        // printf("%d
    ", n);
        // for (int i = 1; i <= n; i++)
        // {
        //     cout << s[i];
        // }
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                f[i][j] = (i == j) ? 1 : inf;
            }
        }
        // printf("n = %d
    ", n);
        for (int len = 2; len <= n; len++)
        {
            for (int i = 1, j = i + len - 1; i <= n - len + 1; i++, j++)
            {
                // printf("i = %d,j = %d,%d
    ", i, j, i <= n);
                for (int k = i; k < j; k++)
                {
                    f[i][j] = min(f[i][j], f[i][k] + f[k + 1][j]);
                }
                for (int k = i; k < j; k++)
                {
                    int L = (k - i + 1);
                    if (len % L != 0)
                        continue;
                    int ck = check(i, k, j);
                    // printf("check(%d,%d,%d) = %d
    ", i, k, j, ck);
                    if (ck > 0)
                    {
                        f[i][j] = min(f[i][j], f[i][k] + Getlen(len / L) + 2);
                    }
                }
            }
        }
        printf("%d
    ", f[1][n]);
        return 0;
    }
    
  • 相关阅读:
    【POJ1743】Musical Theme(后缀数组,二分)
    【BZOJ1031】字符加密Cipher(后缀数组)
    gui线程
    线程同步
    多线程
    java记事本
    gui界面2048小游戏
    IO流+数据库课后习题
    数据库(批处理, 事务,CachedRawSetImpl类
    java(try块语句变量,和匿名类变量生存时间
  • 原文地址:https://www.cnblogs.com/luyiming123blog/p/P4302.html
Copyright © 2011-2022 走看看