单词拼接
-
描述
-
给你一些单词,请你判断能否把它们首尾串起来串成一串。
前一个单词的结尾应该与下一个单词的道字母相同。
如
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 ***
-
第一行是一个整数N(0<N<20),表示测试数据的组数
有向图G 为欧拉回路:
当且仅当G 的基图连通,且所有顶点的入度等于出度。
有向图G 为欧拉路:
当且仅当G 的基图连通,且只存在一个顶点u 的入度比出度大1、
只存在一个顶点v 的入度比出度小1,其它所有顶点的入度等于出度。
分析:此题应把单词的首字母和尾字母抽离出来,首字母出度+1,尾字母入度+1,这样就可以根据每个字母的出度和入度判断起点和终点。特别的,如果是欧拉回路的话,任何一点就可以作为起点,这时候我们按照题意选择字典顺序靠前的.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char str[1000][31];//存储字符串
bool used[1000]; //dfs的时候判断单词是否用过
int In[26]; //入度
int Out[26]; //出度
int s[1000];//在Judge中用来存放每个字符串的大小Size
int stack[1000]; //dfs存储结果
int n;
int compare(const void *a, const void *b)//字符串排序
{
char *p1 = (char *)a;
char *p2 = (char *)b;
return strcmp(p1, p2);
}
int Judge()//检测欧拉
{
int i;
int last = -1;
int first = -1;
for(i = 0; i < 26; ++i)
{
if(In[i] != Out[i])
{
//Out为在串首出现的次数,In为串尾出现的次数
if(Out[i] - In[i] == 1 && first == -1)
first = i;
else if(Out[i] - In[i] == -1 && last == -1)
last = i;
else
return -1;
}
}
if(first > -1 && last > -1) //欧拉通路
return first;
else if(first == -1 && last == -1) //欧拉回路
{
for(i = 0; i < 26; ++i)
if(In[i] != 0)
return i;
}
else
return -1;
}
bool DFS(char first, int Index)//有可能有多个连通区域
{
if(Index == n) //加了这个判断.就不用并查集检测了
return true;
int i;
int b,e,m;
b = 0;
e = n - 1;
while(b <= e)//二分法查找这个首字符,排序好的,肯定快啊。速度绝对比别人快2倍
{
m = (b + e)/2;
if(str[m][0] == first)
break;
else if(str[m][0] > first)
e = m - 1;
else
b = m + 1;
}
if(b > e)
return false;
//找到这个字符第一次出现的字符串
while(str[m][0] == first && m >= 0)
--m;
for(i = m + 1; str[i][0] == first; ++i)
{
if(!used[i])
{
stack[Index] = i;
used[i] = true;
if(DFS(str[i][s[i] - 1], Index + 1))
return true;
used[i] = false;
}
}
return false;
}
int main()
{
int t;
int i,first;
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
for(i = 0; i < n; ++i)
scanf("%s", str[i]);
memset(used, 0, sizeof(used));
memset(In, 0, sizeof(In));
memset(Out, 0, sizeof(Out));
qsort(str, n, 31 * sizeof(char), compare); //字符串排序
for(i = 0; i < n; ++i) //抽离首尾字母统计出入度
{
s[i] = strlen(str[i]);
++Out[str[i][0] - 'a'];
++In[str[i][s[i] - 1] - 'a'];
}
first = Judge(); //判断起点
if(first != -1 && DFS(first + 'a', 0))
{
for(i = 0; i < n - 1; ++i)
printf("%s.", str[stack[i]]);
printf("%s\n", str[stack[n - 1]]);
}
else
printf("***\n");
}
}