POJ2408
本题题意是,把可以通过重新排列变成相同单词的单词放入一个集合,最后按找集合元素由多到少输出前五个集合,如果几何元素相同,按照字典序由小到大输出
我们考虑,如果两个单词可以通过重新排列组合变成相同单词,那么他们的字典序最小的排列方式一定是相同的,所以我们可以利用每个元素的最小排列方式判定是否在同一个集合,字典树在这里用于判定某个字符串时候出现过。最后用set来保存以便维持字典序
POJ2408代码
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<set>
#include<vector>
using namespace std;
const int maxn = 1e6+5;
int tree[maxn][30];
char ss[maxn];
int tot,anstot;
int num[30];
int vis[maxn];
struct data
{int num;set<string> s;
}cnt[maxn];
bool cmp(const data &a,const data &b)
{if(a.num==b.num){return *(a.s.begin())<*(b.s.begin());}return a.num>b.num;
}
void insert_(char *str)
{int root=0;int len= strlen(str);string str2="";for(int i=0;i<len;i++){num[str[i]-'a']++;}for(int i=0;i<26;i++)//在此转换为字典序最小的字符串{while(num[i]!=0){str2+=(i+'a');num[i]--;}}for(int i=0;i<len;i++){int id=str2[i]-'a';if(!tree[root][id]) tree[root][id]=++tot;root=tree[root][id];}if(!vis[root]) vis[root]=++anstot;//若未出现过,赋予编号cnt[vis[root]].num++;//将此字符串所在的结构体num变量+1string tmp=str;cnt[vis[root]].s.insert(tmp);return ;
}
int main()
{while(scanf("%s",ss)!=EOF){insert_(ss);}sort(cnt+1,cnt+1+anstot,cmp);for(int i=1;i<=5;i++){printf("Group of size %d: ",cnt[i].num);set<string>::iterator it;for(it=cnt[i].s.begin();it!=cnt[i].s.end();++it){printf("%s ",(*it).c_str());}printf(".\n");}return 0;
}