题意:求一个字符串能够缩写的最小长度,设字符串S,s,则缩写规则为若S=(s+s+s+s+...+s)共k个s,则S可缩写为k(s)。
思路:区间dp,设一个字符串s最小长度为dp[i][j],其某个子串为s'且S=(s+s+s+...+s)共l个,i为字符串起始下标,j为终止下标。
则字符串s最小的长度=min(j-i+1,dp[i][k]+dp[k+1][i],2+l的位数+s的长度)。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
using namespace std;
#define inf 0x3f3f3f3f
string s;
int t;
int dp[101][101];
int bit(int num)//求num的位数
{
int sum=0;
while(num>0)
{
++sum;
num/=10;
}
return sum;
}
int zip(int l,int r)//求一个字符串压缩成其一个子串的长度
{
int len=r-l+1,k,sum=inf;
bool flag;
for(int i=1;i<=len/2;++i)
{
if(len%i)continue ;
flag=true;
for(int j=l;j<l+i;++j)
{
k=j+i;
while(k<=r)
{
if(s[j]!=s[k])
{
flag=false;
break;
}
k+=i;
}
if(!flag)break;
}
if(flag)
sum=min(sum,bit(len/i)+2+dp[l][l+i-1]);
}
return sum;
}
int main()
{
scanf("%d",&t);
int r;
while(t--)
{
cin>>s;
for(int i=0;i<s.size();++i)
dp[i][i]=1;
for(int d=2;d<=s.size();++d)
for(int i=0;i<=s.size()-d;++i)
{
r=i+d-1;
dp[i][r]=min(d,zip(i,r));
for(int k=i;k<r;++k)
dp[i][r]=min(dp[i][r],dp[i][k]+dp[k+1][r]);
}
printf("%d\n",dp[0][s.size()-1]);
}
}