• Jzoj3443 压缩


    一个文本压缩后由若干个单元组成,每个单元由3部分组成:1.正文(小写字母组成的字符串)2.若干个”*”,表示正文的又重复了几次3.单元的结尾符号”$”,显然,对于同一文本,压缩后的表示方法不唯一,但是为了方便,我们要求你采用压缩后字符串最短的压缩方法,如果有多种压缩方法,只需输出任意一种。n<=2000

    看到数据范围我们发现可以用dp,设f[i][j]表示目前在第i位,最后一个循环串的长度为j的情况下,最短的长度

    那么显然,无论怎么样,有一种转移总是成立的,f[i][j]=min(f[i-j][k]+j+1),这相当于新开了一个循环节

    而另一个转移需要满足一个条件,f[i][j]=min(f[i-j][j]+1),当s(i-j+1,i)=s(i-j*2+1,i-j)时,这相当于在循环节里面加入一个*

    那么综合下来转移就是n^3的,我们加上两个优化

    1.令g[i]为min(f[i][k]),避免每次枚举k

    2.判断字串相等用hash

    这样我们可以将复杂度将为n^2

    接下来说一下如何输出方案

    先记录下s[i][j]表示状态i,j的最后一个循环节j循环次数,和上面两种转移对应,s[i][j]=1或者s[i][j]=s[i][i-j]+1

    我们令d[i]表示答案为g[i]时,最后一个循环节的循环次数,令r[i]为此循环节的长度,那么求解g[i]时,就可以顺便求解d[i]和r[i]

    最后输出即可

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define L long long
    using namespace std;
    int n,m=0; char str[2010],A[2010];
    int f[2010][2010],b[2010],d[2010];
    int h[2010],g[2010],s[2010][2010],r[2010];
    __attribute__((optimize("-O3")))
    inline L gH(int l,int r){ return h[r]-h[l-1]*b[r-l+1]; }
    int main(){
    	freopen("compress.in","r",stdin);
    	freopen("compress.out","w",stdout);
    	scanf("%s",str+1); n=strlen(str+1);
    	for(int i=*b=1;i<=n;++i){
    		b[i]=b[i-1]*27;
    		h[i]=h[i-1]*27+str[i]-'a';
    	}
    	memset(g,127,sizeof g); *g=0;
    	for(int i=1;i<=n;++i)
    		for(int j=1;j<=i;++j){
    			f[i][j]=g[i-j]+j+1; s[i][j]=1;
    			if(f[i][j]<g[i]){ d[i]=1; r[i]=j; g[i]=f[i][j]; }
    			if(i>=(j<<1) && gH(i-j+1,i)==gH(i-j*2+1,i-j))
    				if(f[i][j]>f[i-j][j]+1){
    					s[i][j]=s[i-j][j]+1;
    					f[i][j]=f[i-j][j]+1;
    					if(f[i][j]<g[i])
    						{ d[i]=s[i][j]; r[i]=j; g[i]=f[i][j]; }
    				}
    			g[i]=min(g[i],f[i][j]);
    		}
    	for(;n;){
    		A[m++]='$';
    		for(int i=1;i<d[n];++i) A[m++]='*';
    		for(int i=n;i>n-r[n];A[m++]=str[i--]);
    		n-=r[n]*d[n];
    	}
    	reverse(A,A+m); puts(A);
    }


  • 相关阅读:
    IE6下不能定义1px高度的容器和IE6 双边距
    py django 渲染前端打包的视图
    关于常见的递推关系。
    题解:一些递推的题。
    题解:极值问题。
    题解:城南树林。
    题解:论编辑器的和谐共处。
    题解:左右横跳。
    题解:斑马,斑马(zebra)
    找 前端 私活
  • 原文地址:https://www.cnblogs.com/Extended-Ash/p/9477353.html
Copyright © 2020-2023  润新知