USACO Training Section 3.1 Contact

P2724 联系 Contact

题目背景

奶牛们开始对用射电望远镜扫描牧场外的宇宙感兴趣。最近,他们注意到了一种非常奇怪的脉冲调制微波从星系的中央发射出来。他们希望知道电波是否是被某些地外生命发射出来的,还是仅仅是普通的的星星发出的

题目描述

帮助奶牛们用一个能够分析他们在文件中记下的记录的工具来找到真相。他们在寻找长度在A到B之间(包含A和B本身)在每天的数据文件中重复得最多的比特序列 (1 <= A <= B <= 12)。他们在找那些重复得最多的比特序列。一个输入限制告诉你应输出多少频率最多的序列。

符合的序列可能会重叠,并且至少出现一次的序列会被计数

输入输出格式

输入格式:

第一行: 三个用空格分隔的整数: A, B, N; (1 <= N < 50)

第二行及以后: 一个最多200,000字符的序列,全是0或1; 每行字符数不大于80。

输出格式:

输出N个频率最高的序列(按照频率由高到低的次序)。由短到长排列频率相同的这些序列,如果长短相同,按二进制大小排列。如果出现的序列个数小于N,输出存在的序列。

对于每个存在的频率,先输出单独包含该频率的一行,再输出以空格分隔的这些序列。每行六个(除非剩下的少于六个)。

输入输出样例

输入样例#1:
2 4 10
01010010010001000111101100001010011001111000010010011110010000000
输出样例#1:
23
00
15
01 10
12
100
11
11 000 001
10
010
8
0100
7
0010 1001
6
111 0000
5
011 110 1000
4
0001 0011 1100

说明

在样例里,序列100出现了12次,而序列1000出现了5次。次数最多的序列是00,出现了23次。

题目翻译来自NOCOW。

USACO Training Section 3.1

分析

比较容易想到的部分是使用一个数组来保存对应的串的数量。当然,这道题当中,运用map来做,是比较方便的。以字符串为形式保存的01串作为键值来保存出现频率。
每次读入一个新的字符,然后以这个字符为结尾向前反向找符合条件的字符串,进行统计。
统计完成之后,对于统计数组按照题目要求进行排序。(首先按照频率,然后按照长度,最后按字典序)
输出是本题的一大难点(当然也是USACO比赛一向都是这么坑人),题目对于输出有诸多要求。
首先,没输出6个串就要换行(谁知道为什么),那么我们用一个变量LCount来计算当前行的串的个数。
其次,USACO对于换行要求比NOIP也高得多,不允许多换行,也不能少换行。题目当中有几个坑点,我提交以后才发现,比如,上一行如果已经满了6个串,那么已经进行了换行,那么接下来输出就不能再多换行了(Line74)。
还有,输出前要首先判断当前频率和上一次输出频率是否相同,相同的话继续输出,否则换行重新输出。
输出条件和坑点还有很多,自己写的时候多多注意。

程序

 1 #include <bits/stdc++.h>
 2 #define LL unsigned long long
 3 using namespace std;
 4 map<string,int> s;
 5 int a,b,n,i,j,k,len,ls,LCount;
 6 char ch;
 7 char c[5000000];
 8 struct node
 9 {
10     string Str;
11     int Freq;
12 }Ar[100100];
13 int cmp(node x,node y)
14 {
15     if (x.Freq > y.Freq)
16         return 1;
17     if (x.Freq == y.Freq)
18     {
19         if (x.Str.size()<y.Str.size())
20             return 1;
21         if (x.Str.size()==y.Str.size()&&x.Str<y.Str)
22             return 1;
23         return 0;
24     }
25     return 0;
26 }
27 int main()
28 {
29     freopen("contact.in","r",stdin);
30     freopen("contact.out","w",stdout);
31     cin >> a >> b >> n;
32     while ((ch = getchar()) != EOF)
33     {
34         if (ch == '1' || ch == '0') 
35         {
36             len++;
37             c[len]=ch;
38             string S="";
39             int B = max(len+1-b, 1); //一定要比1大
40             for (i = len; i >= B; i--)
41             {
42                 S = c[i] + S;
43                 if (len-i+1 >= a)
44                 {
45                     if (s[S] == 0)
46                     {
47                         ls++;
48                         s[S] = ls;
49                         Ar[s[S]].Str=S;
50                     }
51                     Ar[s[S]].Freq++;
52                 } 
53             }
54         }
55     }
56     sort(Ar+1,Ar+(ls+1),cmp);
57     for (i = 1; i <= ls; i++)
58     {
59         if (n == 0 && Ar[i].Freq != Ar[i-1].Freq)
60             break;
61         if (Ar[i].Freq == Ar[i-1].Freq)
62         {
63             if (LCount % 6 == 0)
64                 cout << Ar[i].Str;
65             else
66                 cout << " " << Ar[i].Str;
67             LCount++;
68             if (LCount % 6 == 0)
69                 cout << endl;
70         }
71         else
72         {
73             n--;
74             if (i != 1 && LCount%6!=0)
75                 printf("
"); //出现之前相同频率的串,如果是6的倍数,结尾就换行了,在此就不用再换行了。 
76             printf("%d
", Ar[i].Freq);
77             cout << Ar[i].Str;
78             LCount=1;
79         }
80     } 
81     if (LCount%6!=0)
82         printf("
");
83     return 0;
84 }
原文地址:https://www.cnblogs.com/OIerPrime/p/8848247.html