单词拼接
时间限制:
3000 ms | 内存限制:
65535 KB
难度:
5
-
描述
-
给你一些单词,请你判断能否把它们首尾串起来串成一串。
前一个单词的结尾应该与下一个单词的道字母相同。
如
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 ***
来源
- Waterloo local 2003.01.25 /POJ 上传者
一开始是爆搜,超时,然后用vector剪了一波枝,就开始永无止境的wa了,找了将近两小时的样例,也没找到错误,不知道为啥,最近经常这样,造数据的能力太弱?好吧,是我太菜,于是换了种思路,根据欧拉回路的性质首先判断能否构成欧拉通路,然后找起点和终点,并保存起点,怎么找起点呢,我们首先对所有字符串按照字典序排序,因为要保证字典序最小,之后标记每个单词的两端,串首代表该字符的出度,串尾代表入度。为什么要这样定义呢??当然,反着来也是可以的,看你怎么理解了。。。接下来就是找起点了,一个点可以当做起点的条件当且仅当该点的出度比入度大一或者所有点的出度和入度相同,不难证明,详情见代码中的euler函数部分。。
#include<map> #include<stack> #include<queue> #include<vector> #include<math.h> #include<stdio.h> #include<iostream> #include<string.h> #include<stdlib.h> #include<algorithm> #include<functional> using namespace std; typedef long long ll; #define inf 1000000000 #define MOD 1000000007 #define maxn 1005 #define lowbit(x) (x&-x) #define eps 1e-9 struct node { char s[35]; }a[maxn],b[maxn]; int vis[maxn],n,cnt,in[30],out[30],rt[maxn]; bool comp(node a,node b) { if(strcmp(a.s,b.s)<0) return 1; return 0; } int euler() { int i,st=-1,ed=-1; for(i=0;i<26;i++) { if(out[i]==in[i]) continue; if(out[i]-in[i]==1 && st==-1) st=i; else if(out[i]-in[i]==-1 && ed==-1) ed=i; else return -1; } //printf("%d %d\n",st,ed); if(st>-1 && ed>-1) return st; if(st==-1 && ed==-1) { for(i=0;i<26;i++) if(out[i]!=0) return i; } return -1; } int dfs(int st,int id) { if(id==n+1) return 1; for(int i=1;i<=n;i++) { if(vis[i] || a[i].s[0]-'a'<st) continue; if(a[i].s[0]-'a'>st) break; rt[id]=i;vis[i]=1; int len=strlen(a[i].s); if(dfs(a[i].s[len-1]-'a',id+1)) return 1; vis[i]=0; } return 0; } int main(void) { int T,i,j; scanf("%d",&T); while(T--) { scanf("%d",&n); memset(in,0,sizeof(in)); memset(out,0,sizeof(out)); memset(vis,0,sizeof(vis)); for(i=1;i<=n;i++) { scanf("%s",a[i].s); out[a[i].s[0]-'a']++; int len=strlen(a[i].s); in[a[i].s[len-1]-'a']++; } int st=euler(); if(st==-1) { printf("***\n"); continue; } sort(a+1,a+n+1,comp); if(dfs(st,1)) { for(i=1;i<n;i++) printf("%s.",a[rt[i]].s); printf("%s\n",a[rt[n]].s); } else printf("***\n"); } return 0; }
-
第一行是一个整数N(0<N<20),表示测试数据的组数