hihocoder 1320 - 压缩字符串 - [hiho一下160周]
Posted tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hihocoder 1320 - 压缩字符串 - [hiho一下160周]相关的知识,希望对你有一定的参考价值。
这道题目可以说是一道非常好非常一颗赛艇的DP题了。
需要注意的是,其中情形3),字符串必然能完全转化为 N(str)形式,如果有N(str1)M(str2)等等另外样式,应该首先使用拼接形式对其进行划分。
那么,我们首先考虑写一个用来压缩情形3)下的字符串的函数zip():
1 char str[105]; 2 int bit(int n) 3 { 4 int cnt=0; 5 while(n>0) 6 { 7 n/=10; 8 cnt++; 9 } 10 return cnt; 11 } 12 int zip(int l,int r) 13 { 14 int len=r-l+1; 15 bool flag; 16 if(len<=4) return len; 17 for(int sec=1;sec<len;sec++)//循环节长度 18 { 19 if(len%sec) continue;//不能完全转化为N(str)形式 20 flag=1; 21 for(int p=1;p<=sec;p++)//遍历循环节中的每个结点 22 { 23 char now=str[l+p-1]; 24 for(int i=l+sec;i<=r;i+=sec)//遍历每个循环节的头结点 25 { 26 if(str[i+p-1]!=now) 27 { 28 flag=0; 29 break; 30 } 31 } 32 if(!flag) break; 33 } 34 if(flag) return(bit(len/sec) + 2 + sec);//如果字符串可以按这个循环节进行压缩 35 } 36 return len; 37 }
使用比较暴力的方法,并不难写,bit()函数返回一个数字是几位数。
既然有了zip()函数,那么就可以进一步考虑状态转移方程了,如下:
dp[i][j] = min( j - i + 1 , dp[i][k] + dp[k+1][j] , zip( i , j ) ); (即情形1) 2) 3)中选取最小的)
其中,dp[i][j]表示字符串str[i,j]的压缩后最短长度。
最后,我们考虑如何进行状态转移,联想到之前http://www.cnblogs.com/dilthey/p/6889141.html中的归并思路,
我们也可以对本题进行一定的归并,首先初始化所有dp[i][i]=1,然后,依次计算出j - i = 1,2,3,……,n-1的dp[i][j],
另外要注意的是,我们要对zip()函数做一点小修改,如果不修改的话,样例都过不了嗷
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define INF 0x3f3f3f3f 5 using namespace std; 6 char str[105]; 7 int dp[105][105]; 8 int bit(int n) 9 { 10 int cnt=0; 11 while(n>0) 12 { 13 n/=10; 14 cnt++; 15 } 16 return cnt; 17 } 18 int zip(int l,int r) 19 { 20 int len=r-l+1; 21 bool flag; 22 if(len<=4) return len; 23 for(int sec=1;sec<len;sec++)//循环节长度 24 { 25 if(len%sec) continue;//不能完全转化为N(str)形式 26 flag=1; 27 for(int p=1;p<=sec;p++)//遍历循环节中的每个结点 28 { 29 char now=str[l+p-1]; 30 for(int i=l+sec;i<=r;i+=sec)//遍历每个循环节的头结点 31 { 32 if(str[i+p-1]!=now) 33 { 34 flag=0; 35 break; 36 } 37 } 38 if(!flag) break; 39 } 40 if(flag) return(bit(len/sec) + 2 + dp[l][l+sec-1]);//如果字符串可以按这个循环节进行压缩 41 } 42 return len; 43 } 44 int main() 45 { 46 int t; 47 scanf("%d",&t); 48 while(t--) 49 { 50 scanf("%s",str+1); 51 int len=strlen(str+1); 52 for(int i=1;i<=len;i++) dp[i][i]=1; 53 for(int l=2;l<=len;l++) 54 { 55 for(int i=1,j=i+l-1;j<=len;i++,j=i+l-1) 56 { 57 int tmp=INF; 58 for(int k=i;k<j;k++) if(tmp>dp[i][k]+dp[k+1][j]) tmp=dp[i][k]+dp[k+1][j]; 59 dp[i][j]=min( min(l,tmp) ,zip(i,j) ); 60 } 61 } 62 printf("%d\\n",dp[1][len]); 63 } 64 }
当然,这不是一种很优化的算法,时间复杂度大概在O(len^3),可以考虑进行一定的优化。不过反正我是想不出
以上是关于hihocoder 1320 - 压缩字符串 - [hiho一下160周]的主要内容,如果未能解决你的问题,请参考以下文章