字母排序问题
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教授会提供感染病毒后的字典和他希望你帮助恢复的字母组。
病毒将计算机中的所有文档都作了相对应的改变。很幸运,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\n"); 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\n",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 \n",cnt); if(cnt!=n) { printf("0\n"); 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]!='\0';i++) { printf("%c",ans[str[i]-'a']+'a'); } printf("\n"); } return 0; }