bzxoj1090 字符串折叠

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
}

 

以上是关于bzxoj1090 字符串折叠的主要内容,如果未能解决你的问题,请参考以下文章

bzoj1090 [SCOI2003]字符串折叠

BZOJ1090: [SCOI2003]字符串折叠

BZOJ1090:[SCOI2003]字符串折叠——题解

bzoj 1090 字符串折叠

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

BZOJ 1090[SCOI2003]字符串折叠