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 }
View Code

使用比较暴力的方法,并不难写,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周]的主要内容,如果未能解决你的问题,请参考以下文章

hihocoder 1320 - 压缩字符串 - [hiho一下160周]

hihocoder 1320 压缩字符串(字符串+dp)

P1320 压缩技术(续集版)

hihoCoder week8 状态压缩·一

hihoCoder1044 (状态压缩DP)

hihoCoder 1048 : 状态压缩·二