• [BZOJ1090][SCOI2003]字符串折叠


    [BZOJ1090][SCOI2003]字符串折叠

    试题描述

    折叠的定义如下:

    1. 一个字符串可以看成它自身的折叠。记作 (S Rightarrow S)

    2. (X(S))(X(X>1))(S) 连接在一起的串的折叠。记作 (X(S) Rightarrow SSSS…S(X个S))

    3. 如果 (A Rightarrow A’, B Rightarrow B’),则 (AB Rightarrow A’B’) 例如,因为 (3(A) Rightarrow AAA, 2(B) Rightarrow BB),所以 (3(A)C2(B) Rightarrow AAACBB),而 (2(3(A)C)2(B) Rightarrow AAACAAACBB)

    给一个字符串,求它的最短折叠。例如 (AAAAAAAAAABABABCCD) 的最短折叠为:(9(A)3(AB)CCD)

    输入

    仅一行,即字符串 (S),长度保证不超过 (100)

    输出

    仅一行,即最短的折叠长度。

    输入示例

    NEERCYESYESYESNEERCYESYESYES
    

    输出示例

    14
    

    数据规模及约定

    见“输入

    题解

    (f(l, r)) 表示对于区间 ([l, r]) 内的字符串最短能压缩成的长度。那么两种转移:第一种,拼接,即 (f(l, r) = min{f(l, k) + f(k + 1, r) | k in [l, r)});第二种,对于周期串,枚举折叠几倍。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    using namespace std;
    #define rep(i, s, t) for(int i = (s); i <= (t); i++)
    #define dwn(i, s, t) for(int i = (s); i >= (t); i--)
    
    #define maxn 110
    
    int n, f[maxn][maxn], fa[maxn];
    char str[maxn];
    
    int cntdig(int x) {
    	int cnt = 0;
    	while(x) cnt++, x /= 10;
    	return cnt;
    }
    
    int main() {
    	scanf("%s", str + 1);
    	n = strlen(str + 1);
    	
    	rep(i, 1, n) rep(j, i, n) f[i][j] = j - i + 1;
    	rep(len, 1, n) rep(l, 1, n - len + 1) {
    		int r = l + len - 1;
    		rep(i, l, r - 1) f[l][r] = min(f[l][r], f[l][i] + f[i+1][r]);
    		fa[1] = fa[2] = 1;
    		rep(i, 2, r - l + 1) {
    			int j = fa[i];
    			while(j > 1 && str[i+l-1] != str[j+l-1]) j = fa[j];
    			fa[i+1] = str[i+l-1] == str[j+l-1] ? j + 1 : 1;
    		}
    		if(fa[r-l+2] < (r - l + 1 >> 1) + 1) continue;
    //		printf("[%d, %d]
    ", l, r);
    //		rep(i, 1, r - l + 2) printf("%d%s", fa[i], i < r - l + 2 ? "->" : "
    ");
    		int tlen = r - l + 2 - fa[r-l+2], ini = tlen;
    		for(; ini < r - l + 1; ini += tlen) if((r - l + 1) % ini == 0)
    			f[l][r] = min(f[l][r], f[r-ini+1][r] + cntdig((r - l + 1) / ini) + 2);
    //		printf("f[%d][%d] = %d
    ", l, r, f[l][r]);
    	}
    	
    	printf("%d
    ", f[1][n]);
    	
    	return 0;
    }
    

    总感觉在哪做过这道题。

  • 相关阅读:
    JS ipad图片拖动缩放 PHP
    PHP 格式化输出 PHP
    PHP Smarty模版使用 PHP
    PHP PDO小试 PHP
    PHP 获取网页所有连接 PHP
    C# 生成不重复随机字符串 (1秒内生成1000000个) PHP
    使用VS 开发PHP PHP
    PHP 扑捉未处理异常 PHP
    PHP 格式化MYSQL返回float类型 PHP
    CheckBox 选中判断及实现单选功能
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/7736275.html
Copyright © 2020-2023  润新知