// compile: make data
// run: ./data < data.in
#include <bits/stdc++.h>
using namespace std;
#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
#ifdef LOCAL
#include <debug/codeforces.h>
#define debug(x...) _debug_print(#x, x);
#define Debug(x...) _debug_print_format(#x, x);
std::ifstream terminal("/dev/tty");
#define PP cerr<<"\033[1;30mpause...\e[0m",terminal.ignore();
#else
#define debug(x...)
#define Debug(x...)
#define PP
#endif
template<typename...Args> void print_(Args...args){((cout<<args<<" "),...)<<endl;}
#define rep(i,a,b) for(int i=(a);i<(int)(b);++i)
#define sz(v) ((int)(v).size())
#define print(...) print_(__VA_ARGS__);
#define FIND(a, x) ((find(a.begin(),a.end(),(x))!=a.end())?1:0)
#define cmin(x,...) x=min({(x),__VA_ARGS__})
#define cmax(x,...) x=max({(x),__VA_ARGS__})
#define INTMAX (int)(9223372036854775807)
#define INF (int)(1152921504606846976)
#define NaN (int)(0x8b88e1d0595d51d1)
#define double long double
#define int long long
#define uint unsigned long long
#define MAXN 200010
struct graph {
struct node {
int u, v, w;
int idx;
bool operator<(const node &other) const {return w < other.w; }
bool operator==(const node &other) const {return v == other.v && w == other.w; }
};
vector<vector<node>> e;
vector<vector<int>> invid;
node &inv(node &edge) {return e[edge.v][invid[edge.u][edge.idx]]; }
int n;
bool directed;
graph(int V, bool D = 0) {
n = V;
e.resize(n), invid.resize(n);
directed = D;
}
void add_edge(int u, int v, int w = 1, int wb = 1) {
e[u].push_back(node{u, v, w, sz(e[u])});
if (!directed) {
e[v].push_back(node{v, u, wb, sz(e[v])});
invid[u].push_back(sz(e[v]) - 1);
invid[v].push_back(sz(e[u]) - 1);
}
}
void graphviz_dump(int plus = 0, string filename = "graph.dot") {
ofstream gf; gf.open(filename);
gf << (directed ? "digraph" : "graph") << " {\n";
gf << " "; rep(i, 0, n) gf << i+plus << " ;"[i==n-1]; gf << endl;
string notation = directed ? " -> " : " -- ";
bool weighted = 0;
for (auto es: e) for (auto edge: es) if (edge.w != 1) weighted = 1;
rep(u, 0, n) {
for (auto edge: e[u]) {
int v = edge.v, w = edge.w;
if (!directed && u > v) continue;
gf << " " << u+plus << notation << v+plus << (weighted ? " ;\n" : ";\n");
}
}
gf << "}\n";
}
pair<vector<int>, vector<int>> bfs(int s) {
queue<int> q; q.push(s);
vector<int> vis(n, 0); vis[s] = 1;
vector<int> dis(n, INF); dis[s] = 0;
vector<int> pre(n); pre[s] = -1;
while (!q.empty()) {
int u = q.front(); q.pop();
for (auto edge: e[u]) {
int v = edge.v;
if (vis[v]) continue;
vis[v] = 1;
dis[v] = dis[u] + 1;
pre[v] = u;
q.push(v);
}
}
return {dis, pre};
}
};
int32_t main() {
ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
string s; cin >> s;
vector<int> A, C, G, T;
rep(i, 0, sz(s)) {
if (s[i] == 'A') A.push_back(i);
else if (s[i] == 'C') C.push_back(i);
else if (s[i] == 'G') G.push_back(i);
else if (s[i] == 'T') T.push_back(i);
}
int Aptr = 0, Cptr = 0, Gptr = 0, Tptr = 0;
graph g(sz(s), 1);
rep(i, 0, sz(s)) {
if (s[i] == 'A') {
if (Aptr+1 < sz(A)) g.add_edge(A[Aptr], A[Aptr+1]);
if (Cptr < sz(C)) g.add_edge(A[Aptr], C[Cptr]);
if (Gptr < sz(G)) g.add_edge(A[Aptr], G[Gptr]);
if (Tptr < sz(T)) g.add_edge(A[Aptr], T[Tptr]);
++Aptr;
}
if (s[i] == 'C') {
if (Aptr < sz(A)) g.add_edge(C[Cptr], A[Aptr]);
if (Cptr+1 < sz(C)) g.add_edge(C[Cptr], C[Cptr+1]);
if (Gptr < sz(G)) g.add_edge(C[Cptr], G[Gptr]);
if (Tptr < sz(T)) g.add_edge(C[Cptr], T[Tptr]);
++Cptr;
}
if (s[i] == 'G') {
if (Aptr < sz(A)) g.add_edge(G[Gptr], A[Aptr]);
if (Cptr < sz(C)) g.add_edge(G[Gptr], C[Cptr]);
if (Gptr+1 < sz(G)) g.add_edge(G[Gptr], G[Gptr+1]);
if (Tptr < sz(T)) g.add_edge(G[Gptr], T[Tptr]);
++Gptr;
}
if (s[i] == 'T') {
if (Aptr < sz(A)) g.add_edge(T[Tptr], A[Aptr]);
if (Cptr < sz(C)) g.add_edge(T[Tptr], C[Cptr]);
if (Gptr < sz(G)) g.add_edge(T[Tptr], G[Gptr]);
if (Tptr+1 < sz(T)) g.add_edge(T[Tptr], T[Tptr+1]);
++Tptr;
}
}
// g.graphviz_dump();
if (A.empty()) {cout << "A" << endl; return 0; }
if (C.empty()) {cout << "C" << endl; return 0; }
if (G.empty()) {cout << "G" << endl; return 0; }
if (T.empty()) {cout << "T" << endl; return 0; }
auto [Adis, Apre] = g.bfs(A[0]);
auto [Cdis, Cpre] = g.bfs(C[0]);
auto [Gdis, Gpre] = g.bfs(G[0]);
auto [Tdis, Tpre] = g.bfs(T[0]);
char start = '\0';
int mindis = INF, end = -1;
rep(i, 0, g.n) {
if (g.e[i].size() == 4) continue;
if (Adis[i] < mindis) mindis = Adis[i], start = 'A', end = i;
if (Cdis[i] < mindis) mindis = Cdis[i], start = 'C', end = i;
if (Gdis[i] < mindis) mindis = Gdis[i], start = 'G', end = i;
if (Tdis[i] < mindis) mindis = Tdis[i], start = 'T', end = i;
}
vector<int> *pre;
if (start == 'A') pre = &Apre;
if (start == 'C') pre = &Cpre;
if (start == 'G') pre = &Gpre;
if (start == 'T') pre = &Tpre;
string res = "";
vector<int> hs(26, 0);
for (auto c: g.e[end]) ++hs[s[c.v]-'A'];
if (hs['A'-'A'] == 0) res = 'A';
else if (hs['C'-'A'] == 0) res = 'C';
else if (hs['G'-'A'] == 0) res = 'G';
else if (hs['T'-'A'] == 0) res = 'T';
// g.graphviz_dump();
while (end != -1) {
res += s[end];
end = (*pre)[end];
}
reverse(res.begin(), res.end());
cout << res << endl;
return 0;
}
If you’re looking to log in to ph333casinologin, the process is pretty straightforward. I had no issues getting in. Check it out and happy gaming!: ph333casinologin
Hey, mates! Had a spin on cashhoardslot. Pretty decent slots, and the payouts seem fair enough. Why not have a try and see? Have a look: cashhoardslot
747phlive is where it’s at now! Loads of live games and a pretty slick interface. I’ve had some winning streaks here. Worth a look if you’re searching for a new spot. 747phlive for the win!
Tried my luck on casinoluckylife and it was a decent experience. Some interesting games, and the site seems legit. Give it a shot if you’re feeling lucky! Check it out: casinoluckylife
Gave 8okgame a play and it’s…okay. Nothing amazing, but not terrible either. If you’re bored and got some time to kill, might be worth a look. You can find them here: 8okgame
Took a punt on 55qqqbet. A lot of betting options available. The interface can be a little tricky at first, can take time to learn. All in all, a decent place to bet if you do the research! Visit: 55qqqbet
Quick access and no fuss. I love that I can jump straight into my favorite games without any annoying glitches. Very reliable platform. 291jililogin
Honestly, I’ve tried a few sites recently but this one is surprisingly smooth. The payouts are fair and the games load fast. Definitely my new favorite spot! Check it out at gbo303slot
I was looking for something stable and secure and this place delivered. Everything works exactly as it should and the connection is solid. Big thumbs up for vnpj888.
Everything from registration to the first deposit was handled professionally. I am very happy with the welcoming bonus I received. Get started with 38jililoginregister
The login process is seamless and the mobile version works perfectly on my phone. It is refreshing to find a site that actually cares about the user experience. Visit phnn7770login
The app installation was a breeze and it runs perfectly on my phone. No lags and very stable connection. Get your copy at lucky999gamedownload.