一道很裸的区间Dp,不过我判断这个字符串的最小循环节时用了kmp,结果后来去看了一下别人的题解,发现,枚举就可以了。。。

具体的不写了。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
using namespace std;
char ss[300];
int n,nex[300],t,dp[300][300];
int get(int x)
{
  int tot=0;
  while (x) tot++,x=x/10;
  return tot;
}
int calc(int lef,int righ)
//用kmp计算当前字符串是否拥有最小循环节?
{
  nex[0]=-1; int now=-1;
  for (int i=lef+1;i<=righ;i++)
  {
      while ((now!=-1)&&(ss[now+1+lef]!=ss[i])) now=nex[now];
      if (ss[now+1+lef]==ss[i]) now++;
      nex[i-lef]=now;
  }
  int sum=righ-lef+1,tot=sum-nex[righ-lef]-1;
  if ((sum%tot==0)&&(tot<sum))  
  return  min(sum,get(sum/tot)+2+dp[lef][lef+tot-1]);
  return sum;
}
int main()
{
  scanf("%d",&t);
  while (t--)
  {
      scanf("%s",ss); int n=strlen(ss);
      int j=0;
    for (int len=1;len<=n;len++)
    for (int i=0;i<n-len+1;i++)
    {
      j=i+len-1;
      dp[i][j]=calc(i,j);//dp转移
      for (int k=i;k<j;k++) 
      dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]);
    }
    printf("%d\n",dp[0][n-1]);
  }
  return 0;
}

 

posted on 2017-12-12 21:14  nhc2014  阅读(179)  评论(0编辑  收藏  举报