USACO-Section 3.1 Contact(枚举)

此处有目录↑

描述

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

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

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

格式

PROGRAM NAME: contact

INPUT FORMAT:

(file contact.in)

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

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

OUTPUT FORMAT:

(file contact.out)

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

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

SAMPLE INPUT

2 4 10
01010010010001000111101100001010011001111000010010011110010000000

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

SAMPLE OUTPUT

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


方法一:通过map枚举

用map枚举计数,最后排序输出答案即可


/*
ID: your_id_here
PROG: contact
LANG: C++
*/
#include <cstdio>
#include <string>
#include <map>
#include <vector>
#include <iostream>
#include <algorithm>

using namespace std;

struct Node {
    string s;
    int cnt;
    Node(const string& ss="",int nn=0):s(ss),cnt(nn) {}
    bool operator < (const Node& a) const {
        if(cnt!=a.cnt)
            return cnt>a.cnt;
        if(s.size()!=a.s.size())
            return s.size()<a.s.size();
        return s.compare(a.s)<0;
    }
};

string s,t;
map<string,int> mp;
vector<Node> ans;
int a,b,n,i,num;

int main() {
    freopen("contact.in","r",stdin);
    freopen("contact.out","w",stdout);
    cin>>a>>b>>n>>s;
    while(cin>>t)
        s+=t;
    while(b>=a) {
        for(int i=s.size()-b;i>=0;--i) {
            t=s.substr(i,b);
            if(mp[t]==0)
                ans.push_back(Node(t));
            ++mp[t];
        }
        --b;
    }
    for(i=0;i<ans.size();++i)
        ans[i].cnt=mp[ans[i].s];
    sort(ans.begin(),ans.end());
    i=0;
    while(n--) {
        if(i==ans.size())
            break;
        cout<<ans[i].cnt<<"\n"<<ans[i].s;
        num=1;
        while(++i<ans.size()&&ans[i].cnt==ans[i-1].cnt) {
            if(num==6) {
                cout<<"\n";
                num=0;
            }
            else
                cout<<" ";
            cout<<ans[i].s;
            ++num;
        }
        cout<<"\n";
    }
    return 0;
}

方法二:通过trie树枚举

由于只含有0和1两种字符,所以可以用数组模拟满二叉树表示trie树
时间是用map的1/5

/*
ID: your_id_here
PROG: contact
LANG: C++
*/
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
#define lson(i) i<<1
#define rson(i) (i<<1)|1

using namespace std;

struct Node {
    string s;
    int cnt;
    Node(const string& ss="",int nn=0):s(ss),cnt(nn) {}
    bool operator < (const Node& a) const {
        if(cnt!=a.cnt)
            return cnt>a.cnt;
        if(s.size()!=a.s.size())
            return s.size()<a.s.size();
        return s.compare(a.s)<0;
    }
};

string s,t;
vector<Node> ans;
int a,b,n,num,trie[8193];//由于可选字符串长度最大为12,则trie高度为13

void query(int i,const string& x) {
    if(x.size()>b)
        return ;
    if(a<=x.size())
        ans.push_back(Node(x,trie[i]));
    query(lson(i),x+"0");
    query(rson(i),x+"1");
}

int main() {
    freopen("contact.in","r",stdin);
    freopen("contact.out","w",stdout);
    int i;
    cin>>a>>b>>n>>s;
    while(cin>>t)
        s+=t;
    memset(trie,0,sizeof(0));
    for(int sta=s.size()-a;sta>=0;--sta) {//添加字符串
        i=1;
        for(int j=0;j<b&&(sta+j)<s.size();++j) {
            i=(s[sta+j]=='0'?lson(i):rson(i));
            ++trie[i];
        }
    }
    query(1,"");//查找所有符合的字符串
    sort(ans.begin(),ans.end());
    i=0;
    while(n--) {
        if(i==ans.size()||ans[i].cnt==0)
            break;
        cout<<ans[i].cnt<<"\n"<<ans[i].s;
        num=1;
        while(++i<ans.size()&&ans[i].cnt==ans[i-1].cnt) {
            if(num==6) {
                cout<<"\n";
                num=0;
            }
            else
                cout<<" ";
            cout<<ans[i].s;
            ++num;
        }
        cout<<"\n";
    }
    return 0;
}

你可能感兴趣的:(枚举,USACO)