将这些符号离散化,建立有向图,小数指向大数,对图进行拓扑排序即可。
对于比较符号间的大小关系,只有两个数的位数相同时,从高到低第一位不同的数可以确定他们的大小关系,其他则不能。且输入数据是从小到大的,我们只需比较当前数与前一个数就行。
对于无法确定的关系,可以用优先队列,可以实现同一时间在队列中的相对关系按字母升序排列,不同时在队列中的,他们之间一定有指向关系。
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <unordered_map>
#define N 10010
#define M 100010
using namespace std;
int n,cnt;
int h[N],ver[M],nxt[M],tot,in[N];
string s,str[N];
unordered_map<string,int> mp;//离散化
vector<string> v1,v2;//前一个数各位,当前数各位
void add(int u,int v){//建有向图
ver[++tot]=v; nxt[tot]=h[u]; h[u]=tot; in[v]++;
}
void split(){//根据'.'分割
v2.clear();
s+='.';
int pr=-1,p;
while((p=s.find('.',pr+1))!=-1){
string ss=s.substr(pr+1,p-pr-1);
if(!mp[ss]) mp[ss]=++cnt,str[cnt]=ss;//;离散化
v2.push_back(ss);
pr=p;
}
}
void topo(){//拓扑排序
priority_queue<string,vector<string>,greater<string> > q;
for(int i=1;i<=cnt;i++){
if(!in[i]) q.push(str[i]);
}
int f=0;
while(q.size()){
string s=q.top(); q.pop();
int x=mp[s];
if(f) printf(".");
f=1;
cout<<s;
for(int i=h[x];i;i=nxt[i]){
int y=ver[i];
if(--in[y]==0) q.push(str[y]);
}
}
}
int main(){
cin>>n>>s;
split(); v1=v2;
for(int i=1;i<n;i++){
cin>>s;
split();
if(v1.size()==v2.size()){//位数相同
for(int j=0;j<v1.size();j++){
if(v1[j]!=v2[j]){//第一个不同的建边
add(mp[v1[j]],mp[v2[j]]);
break;
}
}
}
v1=v2;
}
topo();
return 0;
}