1. 程式人生 > >USACO Training Section 3.1 Contact

USACO Training Section 3.1 Contact

bits 統計 整數 分隔 r+ 每天 tro 變量 strong

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("\n"); //出現之前相同頻率的串,如果是6的倍數,結尾就換行了,在此就不用再換行了。 
76             printf("%d\n", Ar[i].Freq);
77             cout << Ar[i].Str;
78             LCount=1;
79         }
80     } 
81     if (LCount%6!=0)
82         printf("\n");
83     return 0;
84 }

USACO Training Section 3.1 Contact