BZOJ 1090 字符串折叠

Posted on 2016-10-30 22:58  ziliuziliu  阅读(150)  评论(0编辑  收藏  举报

n^3dp。貌似写麻烦了。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 105
#define inf 2000000000
using namespace std;
int rols[maxn][maxn],dp[maxn][maxn],n,nxt[maxn];
char s[maxn],p[maxn];
int kmp(int l,int r)
{
    for (int i=l;i<=r;i++) p[i-l]=s[i];
    memset(nxt,0,sizeof(nxt));int cnt=0;
    for (int i=2;i<=r-l+1;i++)
    {
        while ((cnt) && (p[cnt]!=p[i-1]))
            cnt=nxt[cnt];
        if (p[cnt]==p[i-1]) cnt++;
        nxt[i]=cnt;
    }
    if (!nxt[r-l+1]) return 0;
    if ((r-l+1)%((r-l+1)-nxt[(r-l+1)])) return 0;
    return (r-l+1)-nxt[r-l+1];
}
int calc(int x)
{
    int ret=0;
    while (x) 
    {
        ret++;
        x/=10;
    }
    return ret;
}
int main()
{
    scanf("%s",s);n=strlen(s);
    for (int i=n;i>=1;i--) s[i]=s[i-1];
    for (int i=1;i<=n;i++)
        for (int j=i;j<=n;j++)
            rols[i][j]=kmp(i,j);
    for (int i=1;i<=n;i++) dp[i][i]=1;
    for (int i=2;i<=n;i++)
        for (int j=1;j<=n-i+1;j++)
        {
            dp[j][i+j-1]=inf;
            for (int k=j;k<=i+j-2;k++)
                dp[j][i+j-1]=min(dp[j][i+j-1],dp[j][k]+dp[k+1][i+j-1]);
            if (rols[j][i+j-1]) dp[j][i+j-1]=min(dp[j][i+j-1],calc(i/rols[j][i+j-1])+2+dp[j][j+rols[j][i+j-1]-1]);
        }    
    printf("%d\n",dp[1][n]);
    return 0;
}