While dad was at work, a little girl Tanya decided to play with dad's password to his secret database. Dad's password is a string consisting of n + 2 characters. She has written all the possible n three-letter continuous substrings of the password on pieces of paper, one for each piece of paper, and threw the password out. Each three-letter substring was written the number of times it occurred in the password. Thus, Tanya ended up with n pieces of paper.
Then Tanya realized that dad will be upset to learn about her game and decided to restore the password or at least any string corresponding to the final set of three-letter strings. You have to help her in this difficult task. We know that dad's password consisted of lowercase and uppercase letters of the Latin alphabet and digits. Uppercase and lowercase letters of the Latin alphabet are considered distinct.
The first line contains integer n (1 ≤ n ≤ 2·105), the number of three-letter substrings Tanya got.
Next n lines contain three letters each, forming the substring of dad's password. Each character in the input is a lowercase or uppercase Latin letter or a digit.
If Tanya made a mistake somewhere during the game and the strings that correspond to the given set of substrings don't exist, print "NO".
If it is possible to restore the string that corresponds to given set of substrings, print "YES", and then print any suitable password option.
5 aca aba aba cab bac
YES abacaba
4 abc bCb cb1 b13
NO
7 aaa aaa aaa aaa aaa aaa aaa
YES aaaaaaaaa
题目给出n个字符串,要求将这n个字符串连接在一起,要求后缀与前缀(两个字符)相同,如aba,bac就可以连接abac,然后输出欧拉路径。
首先有向图,整个图是否连通,欧拉路径的判断 仅有1组或0组(入度= 出度+1,出度 = 入度+1) ,其他的入度==出度
对欧拉路径的输出问题:
首先找到出度大于入度的点,如果没有找任意一点。
进行dfs,深搜的过程中修改head[u],保证之前搜过的不会再搜,之后搜过的也不会被搜到:
for(i = head[u] ; i != -1 ; i = head[u] )//后面搜到的不会再搜
{
if( vis[i] == 0 )
{
vis[i] = 1 ;
head[u] = edge[i].next ;//前面搜到的不会再搜
dfs(edge[i].v) ;
}
}
在最后记录搜索的节点,这样就能保证欧拉路径最后的节点一定出现在最后。
#include <cstdio> #include <cstring> #include <algorithm> #include <map> #include <string> using namespace std ; //欧拉路径:每个边只经过一次,如果是一个圈,称为欧拉回路 struct node { int v ; int next ; } edge[2100000]; int head[2000000] , cnt , vis[2000000] ; int in[100000] , out[100000] , p_num , c[2100000] ; void add(int u,int v) { edge[cnt].v = v ; edge[cnt].next = head[u] ; head[u] = cnt++ ; return ; } void dfs(int u) { int i , v ; for(i = head[u] ; i != -1 ; i = head[u] ) { if( vis[i] == 0 ) { vis[i] = 1 ; head[u] = edge[i].next ; dfs(edge[i].v) ; } } c[p_num++] = u ; } int main() { int n , i , j , u , v ; char str[10] ; memset(head,-1,sizeof(head)) ; memset(vis,-1,sizeof(vis)) ; cnt = 0 ; p_num = 0 ; scanf("%d", &n) ; for(i = 0 ; i < n ; i++) { scanf("%s", str) ; u = str[0]*1000+str[1] ; v = str[1]*1000+str[2] ; add(u,v) ; if( vis[u] == -1 ) { vis[u] = p_num ; c[p_num++] = u ; } if( vis[v] == -1 ) { vis[v] = p_num ; c[p_num++] = v ; } in[ vis[u] ]++ ; in[ vis[v] ]-- ; } int flag1 = 0 , flag2 = 0 ; for(i = 0 ; i < p_num ; i++) { if( in[i] < -1 || in[i] > 1 ) break ; if( in[i] == 1 ) flag1++ ; if( in[i] == -1 ) flag2++ ; } if( i < p_num || !( flag1 == flag2 && flag1 <= 1 ) ) { printf("NO\n") ; return 0; } u = c[0] ; for(i = 0 ; i < p_num ; i++) if( in[i] == 1 ) u = c[i] ; p_num = 0 ; memset(vis,0,sizeof(vis)) ; dfs(u) ; if( p_num < n+1 ) { printf("NO\n") ; return 0 ; } printf("YES\n") ; printf("%c%c", c[p_num-1]/1000 , c[p_num-1]%1000) ; for(i = p_num-2 ; i >= 0 ; i--) printf("%c", c[i]%1000) ; printf("\n") ; return 0 ; }