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;
}
}