zoukankan      html  css  js  c++  java
  • 字母排序问题

    http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=1806

    字母排序问题

    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
    分析:首先统计题目中出现的字母,如果与n相同则继续;否则结束;然后对输入的单词,每相邻的两个进行比较,建立单向图,然后拓扑排序,如果不能完成拓扑排序或者拓扑排序的结果不是唯一的则输出0,否则输出对应的正确单词:
    程序:
    #include"stdio.h"
    #include"string.h"
    #define M 50050
    #define inf 1000000000
    char ch[M][100],str[2222];
    int in[33],use[33];
    int main()
    {
        int G[33][33];
        int n,m,i,j,k;
        while(scanf("%d%d",&n,&m)!=-1)
        {
            for(i=1;i<=m;i++)
                scanf("%s",ch[i]);
            scanf("%s",str);
            memset(G,0,sizeof(G));
            memset(in,0,sizeof(in));
            memset(use,0,sizeof(use));
            for(i=2;i<=m;i++)
            {
                int L1=strlen(ch[i-1]);
                int L2=strlen(ch[i]);
                int L;
                if(L1<L2)
                    L=L1;
                else
                    L=L2;
                for(j=0;j<L;j++)
                {
                    if(ch[i][j]==ch[i-1][j])continue;
                    int a=ch[i-1][j]-'a';
                    int b=ch[i][j]-'a';
                    G[a][b]=1;
                    use[a]=use[b]=1;
                    in[b]++;
                    break;
                }
            }
            int sum=0;
            for(i=0;i<8;i++)
                if(use[i])
                sum++;
            if(sum!=n)
            {
                printf("0
    ");
                continue;
            }
            int cnt=0;
            int s[33];
            for(k=1;k<=n;k++)
            {
                int flag=0;
                for(i=0;i<26;i++)
                {
                    if(use[i]&&in[i]==0)
                    {
                        flag++;
                    }
                }
                //printf("::%d
    ",flag);
                if(flag>=2||flag==0)
                    break;
                for(i=0;i<26;i++)
                {
                    if(!use[i])continue;
                    if(in[i]==0)
                    {
                        in[i]--;
                        s[cnt]=i;
                        cnt++;
                        for(j=0;j<=26;j++)
                        {
                            if(G[i][j]&&use[j])
                            {
                                in[j]--;
                            }
                        }
                        break;
                    }
                }
            }
            //printf("%d 
    ",cnt);
            if(cnt!=n)
            {
                printf("0
    ");
                continue;
            }
            int j=0;
            int ans[33];
            for(i=0;i<26;i++)
            {
                if(use[i])
                {
                    ans[s[j++]]=i;
                }
            }
            for(i=0;str[i]!='';i++)
            {
                printf("%c",ans[str[i]-'a']+'a');
            }
            printf("
    ");
        }
        return 0;
    }
    


  • 相关阅读:
    Java对象序列化/反序列化的注意事项
    初尝Java序列化/反序列化对象
    Java的byte数组
    在C#或者SWT上跨进程访问SWT控件的问题
    Enum实现单例模式
    看个泛型的例子
    构造器优化需要多个构造器的类(建造者模式)
    线程间操作无效: 从不是创建控件的线程访问它.
    SWT中的多线程(Invalid thread access)
    读书笔记 --腾讯传
  • 原文地址:https://www.cnblogs.com/mypsq/p/4348163.html
Copyright © 2011-2022 走看看