题解:
区间DP
考虑状态的设计:
(dp[i][j][0/1])表示原字符串的(i-j)区间有无在中间加(M)。并且默认在(i)之前加入(M)压缩后的最小长度,显然有转移:
[dp[i][j][0]=min_{k=i}^j(dp[i][k][0]+j-k)
]
[dp[i][j][0]=min(dp[i][j][0],dp[i][frac {i+j} 2 ][0]+1) (s[i to frac {i+j} 2]==s[frac {i+j} 2 +1 to j])
]
[dp[i][j][1]=min_{k=i}^{j-1}(min(dp[i][k][0],dp[i][k][1])+1+min(dp[k+1][j][0],dp[k+1][j][1]))
]
代码:
#include<bits/stdc++.h>
using namespace std;
namespace Tzh{
const int maxn=55;
char s[maxn];
int dp[maxn][maxn][2],n;
void work(){
scanf("%s",s+1); n=strlen(s+1);
memset(dp,0x3f3f3f3f,sizeof(dp));
for(int i=1;i<=n;i++) dp[i][i][0]=1;
for(int l=2;l<=n;l++)
for(int i=1,j=i+l-1;j<=n;i++,j++){
for(int k=i;k<j;k++)
dp[i][j][0]=min(dp[i][j][0],dp[i][k][0]+j-k);
if(~l&1){
for(int a=i,b=i+l/2;b<=j;a++,b++)
if(s[a]!=s[b]) goto end;
dp[i][j][0]=min(dp[i][j][0],dp[i][i+l/2-1][0]+1);
}
end:
for(int k=i;k<j;k++)
dp[i][j][1]=min(dp[i][j][1],min(dp[i][k][0],dp[i][k][1])+
1+min(dp[k+1][j][0],dp[k+1][j][1]));
}
printf("%d",min(dp[1][n][1],dp[1][n][0]));
return ;
}
}
int main(){
Tzh::work();
return 0;
}