CSU1620: A Cure for the Common Code(KMP+区间DP)

来源:互联网 发布:pid控制算法和图解 编辑:程序博客网 时间:2024/06/04 23:18

Description

Input

Output

Sample Input

abcbcbcbcaabbbcdcdcdabbbcdcdcd0

Sample Output

Case 1: 7Case 2: 11

HINT

Source


题意:把字符串简化,问简化得到的最短长度是多少

思路:要简化首先要求循环节,这里用kmp解决,而要求所有简化中最短的的话,用区间dp可以求得


<pre name="code" class="cpp">#include <iostream>#include <stdio.h>#include <string.h>#include <stack>#include <queue>#include <map>#include <set>#include <vector>#include <math.h>#include <bitset>#include <algorithm>#include <climits>using namespace std;#define LS 2*i#define RS 2*i+1#define UP(i,x,y) for(i=x;i<=y;i++)#define DOWN(i,x,y) for(i=x;i>=y;i--)#define MEM(a,x) memset(a,x,sizeof(a))#define W(a) while(a)#define LL long long#define N 505#define MOD 19999997#define INF 0x3f3f3f3f#define EXP 1e-8int dp[N][N],next1[N],cas = 1;char s[N];int kmp(char *s,int len)//kmp求循环节的长度{    next1[0] = next1[1] = 0;    int i;    UP(i,1,len-1)    {        int j = next1[i];        W((j&&s[i]!=s[j]))        {            j = next1[j];        }        if(s[i]==s[j])            next1[i+1]=j+1;        else            next1[i+1]=0;    }    return len-next1[len];}int getbit(int x){    int cnt = 0;    W(x)    {        x/=10;        cnt++;    }    return cnt;}void DP(){    int n = strlen(s+1);    int len,l,r,k,i;    UP(i,1,n)    dp[i][i]=1;    UP(len,2,n)//区间dp求解最优值    {        for(l = 1; l+len-1<=n; l++)        {            r = l+len-1;            dp[l][r]=dp[l][l]+dp[l+1][r];            UP(k,l+1,r-1)            {                dp[l][r]=min(dp[l][r],dp[l][k]+dp[k+1][r]);            }            int t = kmp(s+l,len);            if(len%t==0)//现在枚举的串是一个周期循环            {                int tem = dp[l][l+t-1];                if(t>1) tem+=2;//因为不是一个字符的话要加括号                tem+=getbit(len/t);//周期数                dp[l][r]=min(tem,dp[l][r]);            }        }    }    printf("Case %d: %d\n",cas++,dp[1][n]);}int main(){    W(~scanf("%s",s+1))    {        if(s[1]=='0')            break;        DP();    }    return 0;}


0 0