bzxoj1090 字符串折叠

Description

折叠的定义如下: 1. 一个字符串可以看成它自身的折叠。记作S ? S 2. X(S)是X(X>1)个S连接在一起的串的折叠。记作X(S) ? SSSS…S(X个S)。 3. 如果A ? A’, B?B’,则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

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

区间dp,t[i][j]表示i开头长度为j的串的重复次数,f[i][j]表示i开头长度j的串的最短长度。

#include<cstdio>
#include<cstring>
char s[105];
int f[105][105];
int t[105][105];
int v[105];
inline void mins(int&a,int b){if(a>b)a=b;}
int main(){
    for(int i=1;i<10;i++)v[i]=3;
    for(int i=10;i<100;i++)v[i]=4;
    v[100]=5;
    scanf("%s",s);
    int l=strlen(s);
    for(int i=0;i<=l;i++)
        for(int j=1;j<=l;j++)f[i][j]=j;
    for(int i=1;i<=l;i++){
        t[l-i][i]=1;
        for(int j=i+1;j<=l;j++){
            t[l-j][i]=1;
            bool d=1;
            for(int k=0;k<i;k++){
                if(s[l-j+k]!=s[l-j+i+k]){
                    d=0;
                    break;
                }
            }
            if(d)t[l-j][i]=t[l-j+i][i]+1;
        }
    }
    for(int i=1;i<=l;i++){
        for(int j=2;j<=i;j++){
            if(i%j==0){
                int c=i/j;
                for(int k=0;k<l;k++)
                    if(t[k][c]>=j)mins(f[k][i],f[k][c]+v[j]);
            }
        }
        for(int k=0;k<l;k++)
            for(int a=1;a<i;a++)mins(f[k][i],f[k][a]+f[k+a][i-a]);
    }
    printf("%d",f[0][l]);
    return 0;
}
时间: 2024-10-01 05:00:28

bzxoj1090 字符串折叠的相关文章

BZOJ 1090: [SCOI2003]字符串折叠( 区间dp )

按照题意dp...dp(l, r) = min{ dp(l, x) + dp(x+1, r) , 折叠(l, r) } 折叠(l, r)我是直接枚举长度然后哈希判.. -------------------------------------------------------------- #include<bits/stdc++.h> using namespace std; typedef unsigned long long ull; const int maxn = 109; con

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

BZOJ 1090 字符串折叠(区间DP)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1090 题意:字符串AAAAAAAAAABABABCCD的最短折叠为9(A)3(AB)CCD,注意数字的长度和圆括号都算最后长度.求一种折叠方式使得总长度最小. 思路:f[L][R]=min(R-L+1,f[L][i]+f[i+1][R]),另外若[L,R]能由[i+1,R]重复若干次,则也可用折叠后的长度更新f[L][R]. char s[N]; int f[N][N],n; int

【BZOJ-1090】字符串折叠 区间DP + Hash

1090: [SCOI2003]字符串折叠 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1127  Solved: 737[Submit][Status][Discuss] Description 折叠的定义如下: 1. 一个字符串可以看成它自身的折叠.记作S ? S 2. X(S)是X(X>1)个S连接在一起的串的折叠.记作X(S) ? SSSS…S(X个S). 3. 如果A ? A’, B?B’,则AB ? A’B’ 例如,因为3(A) =

BZOJ 1090 字符串折叠(区间DP)

很明显的区间DP,设dp[l][r]表示[l,r]区间的字符串折叠后的最小长度. 可以通过两种方向转移,dp[l][r]=min(dp[l][i]+dp[i+1][r]). 另一种是折叠,dp[l][r]=min(dp[l][l+k-1]+cal((r-l+1)/k)+2).其中k是能整除(r-l+1)的数且区间能够折叠成k份,cal()函数计算数字的位数. 另外用了线段树维护hash值,可以每次验证logn. # include <cstdio> # include <cstring&

bzoj 1090 [SCOI2003]字符串折叠(区间DP)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1090 [题意] 给定一个字符串,问将字符串折叠后的最小长度. [思路] 设f[i][j]表示将区间ij折叠后的最小长度,则有转移式: f[i][j]=min{ j-i+1,f[i][k]+f[k+1][j],f[i][i+x-1]+2+digit((j-i+1)/x) } 第一项代表不折叠,第二项代表当前不折叠,第三项代表以x长度折叠ij区间,条件是满足ij区间以x为循环节. [代码

[SCOI2003]字符串折叠(区间dp)

P4302 [SCOI2003]字符串折叠 题目描述 折叠的定义如下: 一个字符串可以看成它自身的折叠.记作S = S X(S)是X(X>1)个S连接在一起的串的折叠.记作X(S) = SSSS-S(X个S). 如果A = A', B = B',则AB = A'B' 例如,因为3(A) = AAA, 2(B) = BB,所以3(A)C2(B) = AAACBB,而2(3(A)C)2(B) = AAACAAACBB 给一个字符串,求它的最短折叠.例如AAAAAAAAAABABABCCD的最短折叠为

字符串折叠&amp;压缩(区间DP)

字符串折叠 题目描述 折叠的定义如下: 一个字符串可以看成它自身的折叠.记作S = S X(S)是X(X>1)个S连接在一起的串的折叠.记作X(S) = SSSS…S(X个S). 如果A = A’, B = B’,则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. 输

BZOJ1090: [SCOI2003]字符串折叠

链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1090 Description 折叠的定义如下: 1. 一个字符串可以看成它自身的折叠.记作S ? S 2. X(S)是X(X>1)个S连接在一起的串的折叠.记作X(S) ? SSSS-S(X个S). 3. 如果A ? A', B?B',则AB ? A'B' 例如,因为3(A) = AAA, 2(B) = BB,所以3(A)C2(B) ? AAACBB,而2(3(A)C)2(B)?AAACAA