USACO 3.1 Contact (contact)

/*
 经典的位运算解题,边读入边计算。 设置极限掩码为limit=(1<<(B))-1; //2的B此次方-1 
每读入一个二进制数0或1,令unsigned int数字串str=((str<<1)+c) & limit; 
然后扫描str,从末尾向前扫描i=(A到B)位,把所得的数字串t最高位添加1,以区别有前导0的串,例如001和01,添加后变为1001和101

mask=(1<<i)-1;
mask2=mask+1;
t=(S & mask) | mask2;
用哈希表记录t的频率 hash[t]++;

最后再排序按格式输出即可,一定要小心输出格式。
-- refer to byVoid
*/

/*
ID: haolink1
PROG: contact
LANG: C++
*/

//#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>    // std::sort
using namespace std;
typedef unsigned int u_int;

class Pattern{
public:
    u_int freq_;
    u_int value_;
    Pattern(int freq,u_int value):
        freq_(freq),value_(value){}
};

int A = 0,B = 0,N = 0;
const int MAX = (1<<13);
u_int hash[MAX];
void Vote(unsigned int str, unsigned int str_len){
    for(int i = A; i <= B && i <= str_len; i++){
       u_int mask = (1 << i) -1;
       u_int mask2 = mask + 1;
       u_int t = (str & mask) | mask2;
       hash[t]++;
    } 
}
bool Compare(Pattern p1,Pattern p2 ){
    if(p1.freq_ > p2.freq_){
        return true; 
    }else if(p1.freq_ == p2.freq_ && p1.value_ < p2.value_){//Shorter string have less value,eg 101(len = 2) and 1001(len =3)
        return true;
    }else return false;
}

void ChangeFormat(u_int source,char target[]){
    int bit_num = A;
    for(;bit_num <= B; bit_num++){
        if(!(source >> (bit_num+1)))
            break;
    }
    for(int i = bit_num -1; i >= 0; i--){
        if(source & (1 <<(bit_num - i - 1))){
            target[i] = '1';
        }else{
            target[i] = '0';
        }
    }
    target[bit_num] = '\0';
}

int main(){
    ifstream fin("contact.in");
    ofstream cout("contact.out");
    fin >> A >> B >> N;
    char val;
    unsigned int limit = (1 << B)-1;
    unsigned int str, str_len = 0;
    while(fin >> val){
        val -= 48;
        str = ((str << 1) + val) & limit;//The digit highter then B will be kicked off by "limit";
        str_len ++;
        Vote(str,str_len);
    } 
    vector<Pattern> patterns;
    for(int i = 0; i < MAX; i++){
        if(hash[i] != 0){
            patterns.push_back(Pattern(hash[i],i));
        }
    }
    sort(patterns.begin(),patterns.end(),Compare);
    u_int cur_freq = -1 ; 
    int counter = 0;
    int per_line = 1;
    int len = patterns.size();
    for(int i = 0; i < len; i++){
        char target[13];
        if(patterns[i].freq_ < cur_freq){
            counter++;
            per_line = 1;
            if(counter > N){
                break;
            }
            cur_freq = patterns[i].freq_;
            cout << patterns[i].freq_ << endl;
            ChangeFormat(patterns[i].value_,target);
            cout << target;
        }else{
            ChangeFormat(patterns[i].value_,target);
            cout << target;
        }
        //Note condition 1 should put first because  per_line == 0 can be caught by condition 2;
        if((i+1 == len) || (patterns[i+1].freq_ < cur_freq) || (per_line == 0))//condition 1
            cout << endl;
        else if(i+1 < len && patterns[i+1].freq_ == cur_freq)//condition 2
            cout <<" ";
        ++per_line;
        per_line = per_line % 6;
    }
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值