字母排序问题
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
这是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; }