• BZOJ 1090 字符串折叠(Hash + DP)


    题目链接 字符串折叠

    区间DP。$f[l][r]$为字符串在区间l到r的最小值

    正常情况下 $f[l][r] = min(f[l][r], f[l][l+k-1]+f[l+k][r]);$

    当$l$到$r$以$k$为周期时 $f[l][r] = min(f[l][r], 2+sz(k)+f[l][l+(r-l+1)/k-1]);$

    判重的时候为了方便我用了哈希……当然其他方法应该也是可以的~

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define rep(i, a, b)	for (int i(a); i <= (b); ++i)
    #define dec(i, a, b)	for (int i(a); i >= (b); --i)
    
    typedef unsigned long long LL;
    
    const int N = 210;
    const int base = 233;
    
    int f[N][N], n;
    LL bin[N], Hash[N];
    char s[N];
    
    void Hashtable(){
    	bin[0] = 1;
    	rep(i, 1, n) bin[i] = bin[i - 1] * base;
    	rep(i, 1, n) Hash[i] = Hash[i - 1] * base + s[i];
    }
    
    inline LL gethash(int l, int r){
    	return Hash[r] - Hash[l - 1] * bin[r - l + 1];
    }
    
    inline int sz(int x){
    	int ret = 0;
    	for (; x;) ++ret, x /= 10;
    	return ret;
    }
    
    inline bool judge(int l, int m, int r){
    	if ((r - l + 1) % m) return 0;
    	int t1 = (r - l + 1) / m;
    	LL t = gethash(l, l + t1 - 1);
    	for (int i = l; i <= r; i += t1)
    		if (gethash(i, i + t1 - 1) != t) return 0;
    	return 1;
    }
    
    int main(){
    
    	scanf("%s", s + 1);
    	n = strlen(s + 1);
    
    	Hashtable();
    	rep(i, 1, n){
    		rep(j, 1, n){
    			if (j - i + 1 <= n){
    				int l = j, r = i + j - 1;
    				f[l][r] = r - l + 1;
    				rep(k, 1, i){
    					f[l][r] = min(f[l][r], f[l][l + k - 1] + f[l + k][r]);
    					if (judge(l, k, r)) f[l][r] = min(f[l][r], 2 + sz(k) + f[l][l + (r - l + 1) / k - 1]);
    				}
    			}
    		}
    	}
    
    	printf("%d
    ", f[1][n]);
    	return 0;
    }
    
  • 相关阅读:
    Ubuntu 永久修改DNS
    三大主流MQ的组织结构
    nginx基本配置
    CentOS7安装RabbitMQ
    单个表上亿行数据的主键、索引设计,及分页查询
    [SQL]行列转换
    《团队协作的五大障碍》读后感
    【2021-09-26】面对困难是未来绝不后悔的事情
    【2021-09-25】摇摆不定反逼自己脚踏实地
    【一句日历】2021年10月
  • 原文地址:https://www.cnblogs.com/cxhscst2/p/7271485.html
Copyright © 2020-2023  润新知