Description
有n个非空字符串s1~sn,现将其两两连接在一起得到了n*(n-1)个字符串L1 ~Ln*(n-1)
给你L1~Ln*(n-1),要你还原s1 ~ sn,有多解随便造一组即可
n<=50,∑|Li|<=10000
Solution
考虑将所有的Li和Si按长度为第一关键字,字典序为第二关键字排序
设S1<=S2<=S3,那么可以发现L1=Sx+S1或S1+Sx
那么我们可以枚举这个划分点,因为S1是最小的,就找到了S1
接下来考虑依次构造Si,假设我们已经找到了S1 ~ Si-1,将这些字符串构造出的串从L中删掉
考虑当前L中排名最前的串,它一定可以表示成Si+S1或S1+Si
但是如果S1既是L的前缀又是L的后缀怎么办
首先,如果S是合法串,那么S+S1和S1+S一定都出现过,我们判断是否合法
如果都合法我们找另一个串字典序最小的那个
Code
#include <set>
#include <vector>
#include <string>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
struct Str{
string str;
Str(string _st="") {str=_st;}
friend bool operator < (Str a,Str b) {
if (a.str.length()==b.str.length()) return a.str<b.str;
return a.str.length()<b.str.length();
}
};
multiset<Str> t;
typedef multiset<Str> :: iterator it;
int main() {
int n;scanf("%d",&n);
vector<Str> s(n*(n-1));
fo(i,0,n*(n-1)-1) cin>>s[i].str;
sort(s.begin(),s.end());
fo(len,1,s[0].str.length()-1) {
bool ok=1;t.clear();
for(int j=1;j<n*(n-1);j++) t.insert(Str(s[j]));
string a=s[0].str.substr(0,len);
string b=s[0].str.substr(len);
it pos=t.find(Str(b+a));
if (pos==t.end()) continue;
else t.erase(pos);
vector<string> vec({a,b});
if (b.length()<a.length()) swap(a,b);
for(int j=1;j<n*(n-1);j++) {
if (!t.count(Str(s[j]))) continue;
string a1=s[j].str.substr(0,a.length());
string c1=s[j].str.substr(a.length());
string a2=s[j].str.substr(s[j].str.length()-a.length());
string c2=s[j].str.substr(0,s[j].str.length()-a.length());
if (a!=a1&&a!=a2) {ok=0;break;}
string tmp;
if (a==a1&&a==a2) {
it p1,p2;
p1=t.find(c1+a);p2=t.find(a+c2);
if (p1==t.end()&&p2==t.end()) ok=0;
else if (p1!=t.end()&&p2!=t.end()) tmp=(c1+a)<(a+c2)?c1:c2;
else tmp=p1==t.end()?c2:c1;
} else tmp=(a==a1)?c1:c2;
if (!ok) break;
for(auto st:vec) {
it pos=t.find(st+tmp);
if (pos==t.end()) {ok=0;break;}
else t.erase(pos);
pos=t.find(tmp+st);
if (pos==t.end()) {ok=0;break;}
else t.erase(pos);
}
if (!ok) break;
vec.push_back(tmp);
}
if (ok&&vec.size()==n) {
puts("Yes");
for(int i=0;i<vec.size();i++) cout<<vec[i]<<endl;
return 0;
}
}
puts("No");
return 0;
}