// 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; }
No Comments