[SCOI2003]字符串折叠 BZOJ1090 洛谷4302

题目描述

折叠的定义如下:

一个字符串可以看成它自身的折叠。记作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。

输入输出格式

输入格式:
仅一行,即字符串S,长度保证不超过100。

输出格式:
仅一行,即最短的折叠长度。

代码

#include<cstdio>
#include<string>
#include<cstring>
using namespace std;
char s[105];
int len,f[105][105],lst[105][105];
inline int read() {
    int ret=0,f=1;char ch=getchar();
    for (; !isdigit(ch); ch=getchar()) if (ch=='-') f=-f;
    for (; isdigit(ch); ch=getchar()) ret=ret*10+ch-48;
    return ret*f;
}
inline bool can(int l1,int r1,int l2,int r2) {
    if ((r2-l2+1)%(r1-l1+1)) return 0;
    for (int i=l2,j=l1; i<=r2; i++) {
        if (s[i]!=s[j]) return 0;
        if (++j>r1) j=l1;
    }
    return 1;
}
inline int calc(int x) {
    int ret=1,w=10;
    if (x>=w) ret++,w*=10;
    return ret;
}
int main() {
    scanf("%s",s),len=strlen(s);
    for (int i=0; i<len; i++) f[i][i]=1;
    for (int l=2; l<=len; l++)
        for (int i=0; i<=len-l; i++) {
            int j=i+l-1;
            f[i][j]=j-i+1;
            for (int k=i; k<j; k++) {
                if (can(i,k,k+1,j)) f[i][j]=min(f[i][j],f[i][k]+2+calc(l/(k-i+1)));
                f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]);
            }
        }
    printf("%d\n",f[0][len-1]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zj_js_zxb/article/details/80516007