第四届“图灵杯”NEUQ-ACM程序设计竞赛(团队赛)-网络同步赛J(字典树 or map)

问题 J: 简单的变位词
时间限制: 1 Sec 内存限制: 64 MB
提交: 428 解决: 78
[提交][状态][讨论版]
题目描述
变位词是指改变某个词的字母顺序后构成的新词。蔡老板最近沉迷研究变位词并给你扔了一道题:

给你一些单词,让你把里面的变位词分组找出来。互为变位词的归为一组,最后输出含有变位词最多的前五组。如果有组数相同的按照字典序输出。

输入
输入包含由小写字母组成的单词,用换行分割,被EOF终止。 输入数据不超过30000个单词。

输出
输出五组包含单词数量最多的变位词,如果少于五组,输出全部。对每组输出,写出它的大小和成员词,成员词按字典序排序用空格分隔,每组输出之间用换行分隔,相同词只输出一次,但算个数。

样例输入
neuq
tea
bate
beat
caret
trace
nueq
carte
cater
crate
abet
ate
eat
beta
eta
signal
样例输出
Group of size 5: caret carte cater crate trace .
Group of size 4: abet bate beat beta .
Group of size 4: ate eat eta tea .
Group of size 2: neuq nueq .
Group of size 1: signal .
题解:我们把字符串按照升序排序,这样变位词就变成一个相同的串。用字典树来统计个数,用vector来记录答案。
代码:

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
#include<vector>
#include<string.h>
#define ll long long
using namespace std;
vector<string>p[30030];
bool cmp(vector<string> a,vector<string> b)
{
    if(a.size()==b.size())
    {
        return a[0]<b[0];
    }
    else
    return a.size()>b.size();
}
string str[30030];
string s[30030];
int  trie[25000*20][30];
int  val[25000*20];
int cnt=0;
int ge=0;
void insert(string ss,int id)
{
    int now=0;
    for(int i=0;ss[i];i++)
    {
        if(0==trie[now][ss[i]-'a']) trie[now][ss[i]-'a']=++cnt;
        now=trie[now][ss[i]-'a'];
    }
    if(0==val[now])val[now]=++ge;
    p[val[now]].push_back(str[id]);
}
int main()
{
    int tot=0;
    while(cin>>str[++tot])
    {
        s[tot]=str[tot];
        sort(s[tot].begin(),s[tot].end());
        insert(s[tot],tot);
    }
    for(int i=1;i<=ge;i++)
    {
        sort(p[i].begin(),p[i].end());
    }
    sort(p+1,p+1+ge,cmp);
    for(int i=1;i<=5;i++)
    {
        int op=p[i].size();
        if(op==0) break;
        cout<<"Group of size "<<op<<":";
        cout<<" "<<p[i][0];
        for(int j=1;j<op;j++)
        {
            if(p[i][j]!=p[i][j-1])
                  cout<<" "<<p[i][j];

        }  cout<<" ."<<endl;
    }
}

也可以将字典树换成map,更简单(原来不会卡map)。
代码:

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
#include<map>
#include<vector>
#include<string.h>
#define ll long long
using namespace std;
const int N=1e5+10;
map<string ,int> mp;
vector<string>p[30030];
string str[30030];
string s[30030];
int cnt;
void add(string ss,int id)
{
    if(mp.find(ss)==mp.end())
    mp[ss]=++cnt;
    p[mp[ss]].push_back(str[id]);
}
bool cmp(vector<string> a,vector<string> b)
{
    if(a.size()==b.size())
    {
        return a[0]<b[0];
    }
    else
    return a.size()>b.size();
}
int main()
{
     int tot=0;
     cnt=0;
    while(cin>>str[++tot])
    {
        s[tot]=str[tot];
        sort(s[tot].begin(),s[tot].end());
        add(s[tot],tot);
    }
     for(int i=1;i<=cnt;i++)
    {
        sort(p[i].begin(),p[i].end());
    }
    sort(p+1,p+1+cnt,cmp);
    for(int i=1;i<=5;i++)
    {
        int op=p[i].size();
        if(op==0) break;
        cout<<"Group of size "<<op<<":";
        cout<<" "<<p[i][0];
        for(int j=1;j<op;j++)
        {
            if(p[i][j]!=p[i][j-1])
                  cout<<" "<<p[i][j];

        }  cout<<" ."<<endl;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值