Description
一个珍稀书籍的收藏家最近发现了一本用陌生的语言写的一本书,这种语言采用和英语一样的字母。这本书有简单的索引,但在索引中的条目的次序不同于根据英语字母表给出的字典排序的次序。这位收藏家试图通过索引来确定这个古怪的字母表的字符的次序,(即对索引条目组成的序列进行整理),但因为任务冗长而乏味,就放弃了。
请编写程序完成这位收藏家的任务,程序输入一个按特定的序列排序的字符串集合,确定字符的序列是什么。
Input
输入是由大写字母组成的字符串的有序列表,每行一个字符串。每个字符串最多包含20个字符。该列表的结束标志是一个单一字符'#'的一行。并不是所有的字母都被用到,但该列表蕴涵对于被采用的那些字母存在着一个完全的次序。
Output
输出可能存在三种情况:如果不能得到一个完全次序,则输出none;如果次序不唯一,则输出non-unique;如果能唯一确定,则输出字母的排列次序。
Hint
字符串数目最多不超过5000个。
Solution
首先,呃这道题首先就是要找到两个串之间不同的字符然后建立一条有向边,然后由于他这个是按字典序小的来的(虽然我是用的字典序大的加有向边,所以最后输出拓扑序列的时候应该倒着输出(意思就是不影响嘛。。。)),然后预处理完所有的字符串以后就toposort,他这个是多解直接输出non-unique所以只需要用队列就行了(如果是输出字典序最小的那种题的话就要用优先队列维护。),然后输出加上'A'就可以了。
注意事项:
1.不是人做的题。输出的时候加上'A'就可以了。
2.好像也没有什么注意的地方了。
3.占行。
4.占行。
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<vector>
#include<queue>
#define maxn 10005
#define maxm 30
using namespace std;
int h[maxm][maxm],first[maxn],last[maxn],rd[maxn],mark[maxn];
char tmp[maxm],w[maxn][maxm];
int cnt,k,node,n;
vector<int>topo;
struct Edge{
int u;
int v;
int next;
}edge[maxn];
struct data{
int d;
friend bool operator < (data a,data b){
return a.d<b.d;
}
};
void addedge(int u,int v){
edge[++node]=(Edge){u,v,0};
if(first[u]==0)first[u]=node;
else edge[last[u]].next=node;
last[u]=node;
}
void init(){
while(true){
scanf("%s",tmp);
if(tmp[0]=='#')break;
strcpy(w[++cnt],tmp);
}
}
void sett(){
for(int i=1;i<=cnt;i++){
for(int j=1;j<i;j++){
k=0;
while(w[i][k]&&w[j][k]){
if(w[i][k]!=w[j][k])break;
k++;
}
if(w[i][k]&&w[j][k]){
int u=w[i][k]-65,v=w[j][k]-65;
if(h[u][v])continue;
addedge(u,v);
rd[v]++;
h[u][v]=1;
mark[u]++;
mark[v]++;
}
}
}
for(int i=0;i<=26;i++){
if(mark[i])n++;
}
}
int toposort(){
int ret=1;
queue<data>q;
for(int i=0;i<=26;i++){
if(mark[i]>=1&&rd[i]==0){
q.push((data){i});
}
}
while(!q.empty()){
if(q.size()>=2)ret=2;
data t=q.front();
q.pop();
int i=t.d;
topo.push_back(i);
for(int k=first[i];k;k=edge[k].next){
int j=edge[k].v;
if(rd[j]>0)rd[j]--;
if(rd[j]==0)q.push((data){j});
}
}
if(topo.size()<n)ret=0;
return ret;
}
int main(){
init();
sett();
int ok=toposort();
if(ok==2){
printf("non-unique
");
}
else if(ok==0){
printf("none
");
}
else if(ok==1){
for(int i=topo.size()-1;i>=0;i--){
printf("%c",topo[i]+'A');
}
printf("
");
}
return 0;
}