时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524288K 64bit IO Format: %lld
题目描述
给一个由小写字母组成的字符串,我们可以用一种简单的方法来压缩其中的重复信息。 压缩后的字符串除了小
写字母外还可以(但不必)包含大写字母R与M,其中M标记重复串的开始,R重复从上一个M(如果当前位置左边没
有M,则从串的开始算起)开始的解压结果(称为缓冲串)。 bcdcdcdcd可以压缩为bMcdRR,下面是解压缩的过程
另一个例子是abcabcdabcabcdxyxyz可以被压缩为abcRdRMxyRz。
输入描述:
输入仅一行,包含待压缩字符串,仅包含小写字母,长度为n。
输出描述:
输出仅一行,即压缩后字符串的最短长度。
示例1
输入
复制
bcdcdcdcdxcdcdcdcd
输出
复制
12
题解:
我们先考虑没有M的影响
dp[i][j]表示字符串i到j的最短压缩长度
区间dp,我们可以得到:
第一种:没有相等子串的一般情况时
转移dp [ l ] [ r ] = min ( dp [ l ] [ i ] + dp [ i + 1 ] [ r ] ) (l<=i<=r)
第二种:子串长度是偶数,且可以拆分成两个相等的子串时,此时我们可以进行压缩,
mid=(l+r)>>1,
mid+1到r这一段就可以被一个字符R代替
转移dp[l][r]=min(dp[l][r],f[l][mid]+1)
当考虑有M时,R匹配总是与最近的M匹配
我们可以给状态加一维:
dp[l][r][0/1]表示原串l到r在区间内是否有M的最短长度
如果当前区间左一半和右一半相等且中间没有M,我们可以把后一半换成R(和上面讲的情况一样)
dp[l][r][0]=min(dp[l][r][0],dp[l][i][0]+(r-i))(l<=i<=r)
当区间内有M时,就需要将区间分成M之前和之后两部分压缩,因为R只能匹配最近的M,M之前的就管不了了
然后看拆分后的区间的各自情况(看拆分后的区间是有M好还是没M好),记得要+1,因为多加了一个字符M
dp[l][r][1]=min ( dp [l] [r] [1] , min ( dp[l][i][1] , dp[l][i][0] ) +1)
(l<=i<r)i枚举的是M的位置
以上两步都算是正常情况
当区间[l,r]可以拆分成两个相等的部分[l,mid],[mid+1,r]时,
dp[l][r][0]=min(dp[l][r][0],dp[l][mid][0]+1)
最后答案就是取最小值min(dp[1][n][0],dp[1][n][1])
代码:
#include<bits/stdc++.h> using namespace std; const int maxn=85; int dp[maxn][maxn][maxn]; int ans[maxn]; inline int read() { int s=0,f=1; char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(!isdigit(ch)){s=(s<<3)+(s<<1)+ch-48;ch=getchar();} return s*f; } string s; bool check(int l,int r)//检验左右区间是否相等 { int mid=(l+r)>>1; for(int i=l;i<=mid;i++) { if(s[i]!=s[mid+i-l+1])return 0; } return 1; } int main() { cin>>s; int leng=s.length(); s=" "+s; for(int len=1;len<=leng;++len){//从头开始枚举长度 for(int i=1;i+len-1<=leng;++i){ int j=i+len-1; dp[i][j][0]=dp[i][j][1]=len; for (int k=i;k<=j;++k){//从k将区间分为两部分 dp[i][j][0]=min(dp[i][j][0],dp[i][k][0]+j-k); dp[i][j][1]=min(dp[i][j][1],min(dp[i][k][1],dp[i][k][0])+min(dp[k+1][j][0],dp[k+1][j][1])+1); } if(len%2==0&&check(i,j))//如果是偶数,且左右两区间相等 dp[i][j][0]=min(dp[i][j][0],dp[i][(i+j)>>1][0]+1); } } cout<<min(dp[1][leng][0],dp[1][leng][1]); return 0; }