讀入所有單字(至 EOF),將「字母組成相同」(anagram)的單字分為一組。輸出群組大小前 5 大的群組,每組內按字典序輸出不重複單字。群組大小相同時,字典序最小單字較小的群組優先。
對每個單字統計 26 個字母出現次數,構造唯一鍵值。單字長度 ≤ 30,頻率 ≤ 30,可用 64 位整數編碼:
using ULL = unsigned long long;
const int BASE = 31; // > 30 確保無進位衝突
ULL hashKey(const char* s) {
int cnt[26] = {0};
for (int i = 0; s[i]; ++i) ++cnt[s[i]-'a'];
ULL key = 0;
for (int i = 0; i < 26; ++i) key = key * BASE + cnt[i];
return key;
}
BASE=31 保證每個字母計數佔據獨立「位」,等價於 31 進制數,完美無衝突。
#include
#include
#include
#include
#include
using namespace std;
const int MAXN = 30005;
const int MAXL = 30;
const int BASE = 31;
using ULL = unsigned long long;
char word[MAXN][MAXL];
char repWord[MAXN]; // 群組代表單字(字典序最小)
vector groupMembers[MAXN];
vector> vec; // (hash, index)
vector> groups; // (groupId, size)
ULL hashKey(const char* s) {
int cnt[26] = {0};
for (int i = 0; s[i]; ++i) ++cnt[s[i]-'a'];
ULL key = 0;
for (int i = 0; i < 26; ++i) key = key * BASE + cnt[i];
return key;
}
bool cmpGroup(const pair& a, const pair& b) {
if (a.second != b.second) return a.second > b.second; // size 降序
return strcmp(repWord[a.first], repWord[b.first]) < 0; // 代表單字 升序
}
bool cmpWordIdx(int a, int b) {
return strcmp(word[a], word[b]) < 0;
}
int main() {
int N = 0;
while (scanf("%s", word[N]) == 1) {
ULL key = hashKey(word[N]);
vec.emplace_back(key, N);
++N;
}
sort(vec.begin(), vec.end(), [](auto& a, auto& b){ return a.first < b.first; });
int gCnt = 0;
ULL prevKey = ULL(-1);
for (auto& p : vec) {
int idx = p.second;
if (p.first != prevKey) {
if (gCnt > 0) groups.emplace_back(gCnt, (int)groupMembers[gCnt].size());
prevKey = p.first;
groupMembers[gCnt].clear();
strcpy(repWord[gCnt], word[idx]);
++gCnt;
}
groupMembers[gCnt-1].push_back(idx);
if (strcmp(word[idx], repWord[gCnt-1]) < 0)
strcpy(repWord[gCnt-1], word[idx]);
}
if (gCnt > 0) groups.emplace_back(gCnt-1, (int)groupMembers[gCnt-1].size());
sort(groups.begin(), groups.end(), cmpGroup);
int outputCnt = min(5, (int)groups.size());
for (int i = 0; i < outputCnt; ++i) {
int gid = groups[i].first;
printf("Group of size %d: ", groups[i].second);
sort(groupMembers[gid].begin(), groupMembers[gid].end(), cmpWordIdx);
for (int j = 0; j < groupMembers[gid].size(); ++j) {
if (j == 0 || strcmp(word[groupMembers[gid][j-1]], word[groupMembers[gid][j]]) != 0)
printf("%s ", word[groupMembers[gid][j]]);
}
printf(".\n");
}
return 0;
}