码迷,mamicode.com
首页 > 其他好文 > 详细

UVALive - 3363 String Compression 区间DP

时间:2015-07-13 22:30:01      阅读:161      评论:0      收藏:0      [点我收藏+]

标签:

题目大意:有一串字符串,现在有一种转换规则,如果字符串中出现循环的子串,可以将其转化为 :子串数量(子串)
现在问这个字符串的最短长度

解题思路:区间dp,然后分类讨论,这题的难点是如何再进行缩减
将情况分为两种
一种是区间刚好符合缩减情况的,找出该区间的循环节,看能否继续缩减即可
另一种情况就是普通的区间DP了

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define maxn 210
#define INF 0x3f3f3f3f
char str[maxn];
int dp[maxn][maxn];
int vis[maxn][maxn];
int d;

int solve(int s, int e) {
    int len = (e - s + 1) / 2;
    bool mark = true;
    int ans, i;
    for(i = 1; i <= len; i++) 
        if((e - s + 1) % i == 0) { 
            mark = false;
            for(int j = 0; j < i; j++) { 
                char t = str[s + j];
                for(int k = s + j; k <= e; k += i)
                    if(str[k] != t) {
                        mark = true;
                        break;
                    }
                if(mark)
                    break;
            }
            if(!mark) {
                ans  = i;
                d = i;
                break;
            }
        }

    if(!mark) {
        int length;
        if( (e - s + 1) / ans >= 100)
            length = 3;
        else if( (e - s + 1) / ans >= 10)
            length = 2;
        else
            length = 1;

        if(length + 2 + i <= (e - s + 1))  
            return length + 2 + i; 
        else 
            return (e - s + 1);
    }
    else 
        return (e - s + 1);
}

int main() {
    int test;
    scanf("%d", &test);
    while(test--) {
        scanf("%s", str + 1);
        int len = strlen(str + 1);
        memset(vis, 0, sizeof(vis));
        for(int i = 1; i <= len; i++)
            dp[i][i] = 1;
        for(int i = 1; i < len; i++)
            for(int j = 1; j + i <= len; j++) {
                int e = j + i;
                dp[j][e] = solve(j,e);  
                if(dp[j][e] == (e - j + 1))
                    for(int k = j; k < e; k++) 
                        dp[j][e] = min(dp[k + 1][e] + dp[j][k], dp[j][e]);
                else {
                    vis[j][e] = 1;
                    int t = dp[j][e], Min = dp[j][e];
                    for(int duan = 3; duan < d; duan++)
                        for(int start = j; start + duan < j + d; start++) {
                            if(vis[start][start + duan]) {
                                Min = min(Min, t - (duan + 1) + dp[start][start + duan]);
                            }
                        }
                    dp[j][e] = Min;
                }
            }
        printf("%d\n", dp[1][len]);
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

UVALive - 3363 String Compression 区间DP

标签:

原文地址:http://blog.csdn.net/l123012013048/article/details/46867653

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!