POJ2408 模拟排序、char[]操作、利用hash优化

1 题意

给定若干个字符串,将其分组,按照组成元素相同为一组,输出数量最多的前5组,数量相同的输出字典序较小的一组,每组按照字典序输出所有字符串,不输出重复的字符串。

2 分析

主要用到了strcmp()、strncpy()或者strcpy()、sort,以及hash(hash时,要开 unsigned long long )。

代码一(110ms), 加了hash,就是将相同组成元素的单词hash出一个相同的key,然后用pair关联原单词和这个key,这样只需要sort所有的key而不是sort所有单词从而让组成元素相同的单词放在一起以方便分组,然后每个组再sort排一次序。

代码二(800ms),没加hash。

3

代码一

#include <cstdio>
#include <cstring>
#include <vector>
#include <map>
#include <algorithm>
#include <iostream>
using namespace std;

const int maxn=3e+5;
typedef unsigned long long ll;
typedef pair<ll,int> pir;
vector<pir> v;
char word[maxn][30];
struct Group{
    int s[100];
    int number;
}group[maxn];
int zimu[30];
const int maxm=30;
const int X=30;
ll Hash(int cur){
    ll sum=0;
    int len=strlen(word[cur]);
    memset(zimu,0,sizeof(zimu));
    for(int i=0;i<len;i++){
        zimu[word[cur][i]-'a']++;
    }
    for(int i=25;i>=0;i--){
        sum=(sum*30+zimu[i]);
    }
    return sum;
}
int cmp1(pir p1,pir p2){///不同构成元素的单词,key小不一定代表原单词的字典序小(即不能保证包含单词个数相同的组和组是按照组内第一个单词的字典序小的在前排列的)。本次排序的主要目的是:为了让相同构成元素的单词放在一起方便分组,然后相同构成元素的以字典序小的在前以让每一组内单词有序
    if(p1.first!=p2.first){
        return p1.first<p2.first;//不同构成元素的单词,KEY小的在前面
    }
    else if(p1.first==p2.first){
        return strcmp(word[p1.second],word[p2.second])<0;//相同KEY,以原单词的字典序小的在前
    }
}
int cmp2(Group g1,Group g2){
    if(g1.number!=g2.number){
        return g1.number>g2.number;
    }
    else if(g1.number==g2.number){
        return  strcmp(word[g1.s[0]],word[g2.s[0]])<0;
    }
}
int main()
{
    //freopen("out2.txt","w",stdout);
    int cur=0;
    v.clear();

    while(~scanf("%s",word[cur])){
        ll key=Hash(cur);
        v.push_back(make_pair(key,cur));
        cur++;
    }
    sort(v.begin(),v.end(),cmp1);

    int cur2=0;
    group[cur2].number=1;
    group[cur2].s[group[cur2].number-1]= v[0].second;

    for(int i=1;i<cur;i++){
        if(v[i].first!=v[i-1].first){
            cur2++;
            group[cur2].number=1;
            group[cur2].s[group[cur2].number-1]=v[i].second;
        }
        else{
            group[cur2].number++;
            group[cur2].s[group[cur2].number-1]=v[i].second;
        }
    }
    cur2++;

    sort(group,group+cur2,cmp2);

    for(int i=0;i<min(5,cur2);i++){
        printf("Group of size %d: %s ",group[i].number,word[group[i].s[0]]);
        for(int j=1;j<group[i].number;j++){
            if(strcmp(word[group[i].s[j-1]],word[group[i].s[j]])==0)  continue;
            printf("%s ",word[group[i].s[j]]);
        }
        cout<<"."<<endl;
    }
}

代码二

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

const int maxn=3e5+10;
struct Node{
    char s[40];
    char s_[40];
    int len;
}node[maxn];
struct Group{
    char s[100][40];
    int number;
}group[maxn];
int cmp(Node n1,Node n2){
    if(strcmp(n1.s_,n2.s_)==0){
        return strcmp(n1.s,n2.s)<0;
    }
    else{
        return strcmp(n1.s_,n2.s_)<0;
    }
}
int cmp2(Group g1,Group g2){
    if(g1.number==g2.number){
        return strcmp(g1.s[0],g2.s[0])<0;//字典序小的在前面
    }
    else if(g1.number!=g2.number){
        return g1.number>g2.number;
    }
}
int main()
{
    int cur=0;
    while(~scanf("%s",node[cur].s)){
        node[cur].len=strlen(node[cur].s);
        strncpy(node[cur].s_,node[cur].s,node[cur].len);///???
        node[cur].s_[node[cur].len]='\0';
        sort(node[cur].s_,node[cur].s_+node[cur].len);//统一顺序
        cur++;
    }
    sort(node,node+cur,cmp);

    int cur2=0;
    group[cur2].number=1;
    strncpy(group[cur2].s[group[cur2].number-1],node[cur2].s,node[cur2].len);
    group[cur2].s[group[cur2].number-1][node[cur2].len]='\0';

    for(int i=1;i<cur;i++){
        if(strcmp(node[i].s_,node[i-1].s_)==0){
            strncpy(group[cur2].s[group[cur2].number],node[i].s,node[i].len);
            group[cur2].number++;
        }
        else{
            cur2++;
            group[cur2].number=1;
            strncpy(group[cur2].s[group[cur2].number-1],node[i].s,node[i].len);
            group[cur2].s[group[cur2].number-1][node[i].len]='\0';
        }
    }
    sort(group,group+cur2+1,cmp2);//cur2不是指个数了啊

    cur2=min(cur2,5);
    for(int i=0;i<cur2;i++){
        printf("Group of size %d: ",group[i].number);
        printf("%s ",group[i].s[0]);
        for(int j=1;j<group[i].number;j++){
            if(strcmp(group[i].s[j],group[i].s[j-1])==0)   continue;
            printf("%s ",group[i].s[j]);
        }
        cout<<"."<<endl;
    }
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值