【POJ 2408 Anagram Groups】 字典树(Trie树)

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;
}
    原文作者:Trie树
    原文地址: https://blog.csdn.net/qq_38891827/article/details/80673071
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞