题目链接:点击打开链接
题意:给定n个长度为3各不相同的字符串,猜一个n+2位的密码。
这个密码包含上面的所有字符串
思路:
把 abc 拆成ab -> bc
则得到一个图,目标就是走遍所有 ab->bc 这样的边,也就是找一条欧拉通路。
#include <cstdio>
#include <algorithm>
#include <string.h>
#include <queue>
#include <cstring>
#include <cmath>
#include <iostream>
#include <vector>
using namespace std;
typedef pair<int, int> pii;
typedef long long ll;
vector<pii>G[500000];
int deg[4000];
int ans[500000], top;
int v[500000];
int cur[4000];
void eur(int s, int p)
{
int f;
while (cur[s]<G[s].size())
if (v[G[s][f = cur[s]++].second] == 0)
{
v[G[s][f].second] = 1;
eur(G[s][f].first, G[s][f].second);
}
ans[top++] = p;
}
char c[200005][5];
int n;
int ch(char c){
if ('0' <= c && c <= '9')return c - '0';
if ('a' <= c && c <= 'z')return c - 'a' + 10;
return c - 'A' + 36;
}
int getx(int id){
return ch(c[id][0]) * 62 + ch(c[id][1]);
}
int gety(int id){
return ch(c[id][1]) * 62 + ch(c[id][2]);
}
bool ok(){
int x = 0, y = 0, pos = getx(0);
for (int i = 0; i < 4000; i++){
if (deg[i]>1 || deg[i] < -1)return false;
if (deg[i] == 1) x++, pos = i;
if (deg[i] == -1)y++;
}
if (x != y || x>1)return false;
eur(pos, -1); top--;
return top >= n;
}
void input(){
memset(deg, 0, sizeof deg);
memset(cur, 0, sizeof cur);
memset(v, 0, sizeof v);
scanf("%d", &n);
for (int i = 0; i < n; i++){
scanf("%s", c[i]);
int x = getx(i), y = gety(i);
G[x].push_back(pii(y, i));
deg[x]++; deg[y]--;
}
}
int main(){
input();
if (ok())
{
puts("YES");
printf("%s", c[ans[top - 1]]);
for (int i = top - 2; i>-1; i--)
printf("%s", c[ans[i]] + 2);
puts("");
}
else puts("NO");
return 0;
}