Fork me on GitHub

编程之美初赛第二场 题目2 : 字符串压缩

时间限制:8000ms
单点时限:4000ms
内存限制:256MB

描述

你的硬盘上有一个神秘的文件占用了大量空间,你决定将其压缩以节省空间。不幸的是,你还没有安装任何压缩软件,所以你决定自己编写一个压缩程序。你发现这是一个文本文件,包括很多行。每行是一个长度恰好为L的字符串,而且字符串可能有重复。行的顺序并不重要,换言之,打乱顺序之后仍然可以认为文件内容和原来相同。

例如,这个文件的内容可以是这样的:

bar

car

bat

cat

cat

 

经过一段时间观察,你发现同一列的字符往往是相同的,于是你设计了一个简单的压缩框架。首先以某种策略调整行的顺序,然后把所有字符串按照先列后行的顺序变换成单个字符串,例如上面的例子,不调整顺序则直接变换成:

bcbccaaaaarrttt

然后使用游程编码(RLE)的到压缩变换后的字符串:

1b1c1b2c5a2r3t

当然也可以先调换顺序:

car

cat

cat

bat

bar

这样的压缩字符串为:

3c2b5a1r3t1r

比不调整顺序的稍短一些。

现在,你已经得到了两个不同的压缩字符串,你想知道他们解压后的文件是否相同,请写一个程序解决这个问题。

输入

第一行是一个整数T (T <= 30),表示测试数据组数。

每组测试数据占三行。第一行为整数L,表示原始文件中每一行字符串的长度。第二行和第三行分别是两个压缩字符串,格式如c1 n1 c2 n2 … cMnM,表示字符ci连续出现了ni次。具体格式见样例。输入字符串只含a到z的小写字母,确保压缩字符串合法有效,且不为空。

输出

对每组测试数据,首先输出”Case x: ”,其中x表示测试数据编号。如果两个压缩字符串对应于相同的文件内容,则输出”Yes”,否则输出”No”。

数据范围

小数据:1<=L<=10, 1<=ni<=100,压缩字符串长度不超过10^4

大数据:1<=L<=1000, 1<=ni<=10^9,压缩字符串长度不超过10^6

样例输入
2
3
1b1c1b2c5a2r3t
3c2b5a1r3t1r
2
20a20b10a20b10a
20a20b20a20b
样例输出
Case 1: Yes
Case 2: No

 

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 
 5 using namespace std;
 6 
 7 const int MAX = 10000 + 4;
 8 
 9 char str[2][MAX*3];
10 char input[MAX];
11 int L;
12 int lineNum;
13 int Num[2];
14 int visit[MAX*3];
15 
16 int main()
17 {
18     int T;
19     int n;
20     char ch1, ch2;
21     scanf("%d", &T);
22     for(int t=1; t<=T; t++) {
23         scanf("%d", &L);
24         getchar();
25         Num[0] = Num[1] = 0;
26         for(int i=0; i<2; ++i) {
27             scanf("%s", input);
28             int cur = 0;
29             int length = strlen(input);
30             for(int j=0; j<length;  ) {
31                 n = 0;
32                 while(input[j] <= '9' && input[j] >= '0') {
33                     n = n*10 + (input[j++] - '0');
34                 }
35                 Num[i] += n;
36                 for(int k=1; k<=n; k++) {
37                     str[i][cur++] = input[j];
38                 }
39                 j++;
40             }
41            // printf("%s\n", str[i]);
42         }
43         if(Num[0] != Num[1]) {
44             printf("Case %d: No\n", t);
45             continue;
46         }
47         lineNum = Num[0] / L;
48         memset(visit, -1, sizeof(visit));
49         bool res = true;
50         for(int i=0; i<lineNum; ++i) {
51             bool flag = false;
52             for(int j=0; j<lineNum; ++j) {
53                 if(visit[j] != -1) {
54                     continue;
55                 }
56                 int k;
57                 for(k=0; k<L; ++k) {
58                     if(str[0][i+k*lineNum] != str[1][j+k*lineNum]) {
59                         break;
60                     }
61                 }
62                 if(k >= L) {
63                     visit[j] = 1;
64                     flag = true;
65                     break;
66                 }
67             }
68             if(!flag) {
69                 res = false;
70                 break;
71             }
72         }
73         if(res) {
74             printf("Case %d: Yes\n", t);
75         }else {
76             printf("Case %d: No\n", t);
77         }
78     }
79     return 0;
80 }

主要是分配数组的大小,压缩字符串不超过10^4, 1<=ni<=100, 那么存储的字符串至少要:

100*(10000 /(3+1)) = 25000

 
posted @ 2014-04-20 16:07  Gifur  阅读(880)  评论(0编辑  收藏  举报
TOP