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变量+1 string 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; }