字母排序问题

字母排序问题

Time Limit: 1000ms   Memory limit: 65536K  

题目描述

G教授是XOI的负责人,有一天他竟然发现自己的计算机染上了一种不常见的病毒。这种病毒的名字叫做ALPHABETVIRUS,当它发作的时候,会将字母用其他的字母代替,但不会将单词的顺序交换。

病毒将计算机中的所有文档都作了相对应的改变。很幸运,G教授的计算机上有一个字典,而我们都知道字典单词是按字母顺序排列的,当然,这个字典也被病毒改变了。因此,要利用字典原来的有序性,找到病毒替换字母的规律,再用以恢复其他文档。由于XOI不能缺少G教授的文件,所以文档必须恢复。但是由于G教授有其他更重要的工作完成,所以他希望你可以帮助他恢复文档,使得XOI的工作可以继续。

G教授会提供感染病毒后的字典和他希望你帮助恢复的字母组。

输入

第一行是两个整数A(<=26)和K(<=50000),A表示需要恢复的字母个数,K表示字典里与这几个字母有关系的单词个数,他们之间用一个空格隔开。接下的K行按原来的字典顺序给出这K个单词。第K+1行是要你恢复的字母组,字母为小写字母。

输出

将字母组输出,如果不可将字母区分,则输出0。

示例输入

5 6
cebdbac
cac
ecd
dca
aba
bac
cedab

示例输出

abcde
 
 
这是http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=1806上的一道题
拓扑排序,比较每两个相邻的单词来构图。
 
 
AC代码:
#include <cstring>
#include <string>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
#include <vector>
#include <cstdlib>
#include <iostream>
#define max2(a,b) ((a) > (b) ? (a) : (b))
#define min2(a,b) ((a) < (b) ? (a) : (b))

using namespace std;

vector<int>w[30];
queue<int>q;
int main()
{
    int a,n;
    string s[50005];
    string str;
    int in[30];
    bool vis[30];
    int id[30];
    cin>>a>>n;
    for(int i=0;i<a;i++)
    w[i].clear();
    for(int i=0;i<n;i++)
    cin>>s[i];
    cin>>str;
    memset(in,0,sizeof(in));
    memset(vis,false,sizeof(vis));
    for(int i=1;i<n;i++)
    {
       for(int j=0;j<min2((int)s[i-1].length(),(int)s[i].length());j++)
       if(s[i-1][j]!=s[i][j])
       {
           int u=s[i-1][j]-'a';
           int v=s[i][j]-'a';
           w[u].push_back(v);
           in[v]++;
           break;
       }
    }
    for(int i=0;i<a;i++)
    if(in[i]==0)
    q.push(i);
    int cnt=0;
    while(!q.empty())
    {
        if(q.size()>1)
        break;
        int x=q.front();
        id[x]=cnt++;
        vis[x]=true;
        q.pop();
        for(int i=0;i<(int)w[x].size();i++)
        {
            in[w[x][i]]--;
            if(!vis[w[x][i]]&&in[w[x][i]]==0)
            q.push(w[x][i]);
        }
    }
    if(cnt<a)
    {
        printf("0\n");
    }
    else
    {
    for(int i=0;i<(int)str.length();i++)
    {
        printf("%c",id[str[i]-'a']+'a');
    }
    printf("\n");
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值