zoukankan      html  css  js  c++  java
  • [SCOI2003]字符串折叠

    IV.[SCOI2003]字符串折叠

    一眼区间DP。

    \(f[i][j]\)表示:将区间\([i,j]\)内的所有东西压一起的最短长度。

    显然,有两种方法:

    1.在中间一刀劈开,然后拼一起。

    2.找到它的循环节,然后把整个串压一起。

    至于找循环节吗……枚举循环节长度,然后无脑哈希一下。

    注意,你可能会压出类似于\(10(AB)\)这种东西,记得\(10\)是两位数!!!

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef unsigned long long ull;
    char s[110];
    int n,f[110][110];
    ull sd1=998244353,sd2=666623333,pov1[2001000],pov2[2001000];
    struct HASH{
    	ull val1,val2;
    	int len;
    	HASH(){
    		val1=val2=0ull;
    		len=0;
    	}
    	HASH(char ip){
    		val1=val2=ip;
    		len=1;
    	}
    	friend HASH operator +(const HASH &x,const HASH &y){
    		HASH z;
    		z.val1=x.val1*pov1[y.len]+y.val1;
    		z.val2=x.val2*pov2[y.len]+y.val2;
    		z.len=x.len+y.len;
    		return z;
    	}
    	friend HASH operator -(const HASH &x,const HASH &y){
    		HASH z;
    		z.val1=x.val1-y.val1*pov1[x.len-y.len];
    		z.val2=x.val2-y.val2*pov2[x.len-y.len];
    		z.len=x.len-y.len;
    		return z;
    	}
    	friend bool operator ==(const HASH &x,const HASH &y){
    		if(x.len!=y.len)return false;
    		if(x.val1!=y.val1)return false;
    		if(x.val2!=y.val2)return false;
    		return true;
    	}
    }hs[110];
    int calc(int x){
    	int res=0;
    	while(x)res++,x/=10;
    	return res;
    }
    int main(){
    	scanf("%s",s+1),memset(f,0x3f3f3f3f,sizeof(f)),n=strlen(s+1);
    	pov1[0]=pov2[0]=1;
    	for(int i=1;i<=n;i++)pov1[i]=pov1[i-1]*sd1,pov2[i]=pov2[i-1]*sd2;
    	for(int i=1;i<=n;i++)hs[i]=hs[i-1]+HASH(s[i]),f[i][i]=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++)f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]);
    			for(int k=1;k<l;k++){
    				if(l%k)continue;
    				if((hs[j]-hs[i+k-1])==(hs[j-k]-hs[i-1]))f[i][j]=min(f[i][j],f[i][i+k-1]+2+calc(l/k));
    			}
    		}
    	}
    //	for(int i=1;i<=n;i++){for(int j=i;j<=n;j++)printf("%d ",f[i][j]);puts("");}
    	printf("%d\n",f[1][n]);
    	return 0;
    }
    

  • 相关阅读:
    HDU 2078 复习时间
    HDU 2076 夹角有多大
    邮票(codevs 2033)
    特种部队(codevs 1427)
    小a和uim之大逃离(洛谷 1373)
    地铁间谍(洛谷 2583)
    推销员(codevs 5126)
    小朋友的数字(codevs 3293)
    车站分级(洛谷 1983)
    Code(poj 17801)
  • 原文地址:https://www.cnblogs.com/Troverld/p/14596789.html
Copyright © 2011-2022 走看看