题目描述
给你一些单词,请你判断能否把它们首尾串起来串成一串。
前一个单词的结尾应该与下一个单词的道字母相同。
如
aloha
dog
arachnid
gopher
tiger
rat
可以拼接成:aloha.arachnid.dog.gopher.rat.tiger
输入
- 第一行是一个整数N(0<N<20),表示测试数据的组数
每组测试数据的第一行是一个整数M,表示该组测试数据中有M(2<M<1000)个互不相同的单词,随后的M行,每行是一个长度不超过30的单词,单词全部由小写字母组成。
输出
如果存在拼接方案,请输出所有拼接方案中字典序最小的方案。(两个单词之间输出一个英文句号".")
- 如果不存在拼接方案,则输出
***
样例输入
-
2 6 aloha arachnid dog gopher rat tiger 3 oak maple elm
样例输出
-
aloha.arachnid.dog.gopher.rat.tiger ***
#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
using namespace std;
string words[1005];
int vis[1005],ans[1005];
int out[30],in[30],n;
int judge()
{
int start=-1,end=-1;
for(int i=0;i<26;i++)//检查奇点
{
if(out[i]!=in[i])
{
if(out[i]-in[i]==1&&start==-1)
start=i;
else if(out[i]-in[i]==-1&&end==-1)
end=i;
else return -1;
}
}
if(start>-1&&end>-1)//2个奇点
return start;
else if(start==-1&&end==-1) //0个奇点
{
for(int i=0;i<26;i++)
if(out[i]) return i;
}
}
int dfs(char start,int id)
{
if(id==n) return 1;
int x=0,y=n,m;
while(x<y)
{
m=x+(y-x)/2;
if(words[m][0]>=start) y=m;
else x=m+1;
}
if(x==n||words[x][0]!=start) return 0;
for(int i=x;words[i][0]==start;i++)
{
if(!vis[i])
{
ans[id]=i; vis[i]=1;
if(dfs(words[i][words[i].size()-1],id+1))//此处多写了个‘;’,一直WA,打脸吧!!!
return 1;
vis[i]=0;
}
}
return 0;
}
int main()
{
int t;
cin>>t;
while(t--)
{
memset(vis,0,sizeof(vis));
memset(out,0,sizeof(out));
memset(in,0,sizeof(in));
cin>>n;
for(int i=0;i<n;i++)
{
cin>>words[i];
out[words[i][0]-'a']++;
in[words[i][words[i].size()-1]-'a']++;
}
int id=judge();
sort(words,words+n);
if(id!=-1&&dfs(id+'a',0))
{
for(int i=0;i<n-1;i++)
cout<<words[ans[i]]<<".";
cout<<words[ans[n-1]]<<endl;
}
else cout<<"***"<<endl;
}
}