#include <bits/stdc++.h>   using namespace std;   template <typename T>   T in() {     char ch;     T n = 0;     bool ng = false;     while (1) {       ch = getchar();       if (ch ==  - ) {         ng = true;         ch = getchar();         break;       }       if (ch >=  0  && ch <=  9 ) break;     }     while (1) {       n = n * 10 + (ch -  0 );       ch = getchar();       if (ch <  0  || ch >  9 ) break;     }     return (ng ? -n : n);   }   template <typename T>   inline T Dis(T x1, T y1, T x2, T y2) {     return sqrt((x1 - x2 * x1 - x2) + (y1 - y2 * y1 - y2));   }   template <typename T>   inline T POW(T B, T P) {     if (P == 0) return 1;     if (P & 1)       return B * POW(B, P - 1);     else       return (POW(B, P / 2) * POW(B, P / 2));   }   template <typename T>   inline T ABS(T a) {     if (a < 0)       return -a;     else       return a;   }   template <typename T>   inline T Gcd(T a, T b) {     if (a < 0) return Gcd(-a, b);     if (b < 0) return Gcd(a, -b);     return (b == 0) ? a : Gcd(b, a % b);   }   template <typename T>   inline T Lcm(T a, T b) {     if (a < 0) return Lcm(-a, b);     if (b < 0) return Lcm(a, -b);     return a * (b / Gcd(a, b));   }   long long Bigmod(long long base, long long power, long long MOD) {     long long ret = 1;     while (power) {       if (power & 1) ret = (ret * base) % MOD;       base = (base * base) % MOD;       power >>= 1;     }     return ret;   }   long long ModInverse(long long number, long long MOD) {     return Bigmod(number, MOD - 2, MOD);   }   int Set(int N, int pos) { return N = N | (1 << pos); }   int Reset(int N, int pos) { return N = N & ~(1 << pos); }   bool Chkbit(int N, int pos) { return (bool)(N & (1 << pos)); }   bool isVowel(char ch) {     ch = toupper(ch);     if (ch ==  A  || ch ==  U  || ch ==  I  || ch ==  O  || ch ==  E )       return true;     return false;   }   bool isConst(char ch) {     if (isalpha(ch) && !isVowel(ch)) return true;     return false;   }   int toInt(string s) {     int sm;     stringstream ss(s);     ss >> sm;     return sm;   }   long long int toLlint(string s) {     long long int sm;     stringstream ss(s);     ss >> sm;     return sm;   }   const int N = int(2e6) + 15;   int cmp(int *r, int a, int b, int l) {     return (r[a] == r[b]) && (r[a + l] == r[b + l]);   }   int wa[N], wb[N], wws[N], wv[N];   int rnk[N], height[N];   void DA(int *r, int *sa, int n, int m) {     int i, j, p, *x = wa, *y = wb, *t;     for (i = 0; i < m; i++) wws[i] = 0;     for (i = 0; i < n; i++) wws[x[i] = r[i]]++;     for (i = 1; i < m; i++) wws[i] += wws[i - 1];     for (i = n - 1; i >= 0; i--) sa[--wws[x[i]]] = i;     for (j = 1, p = 1; p < n; j *= 2, m = p) {       for (p = 0, i = n - j; i < n; i++) y[p++] = i;       for (i = 0; i < n; i++)         if (sa[i] >= j) y[p++] = sa[i] - j;       for (i = 0; i < n; i++) wv[i] = x[y[i]];       for (i = 0; i < m; i++) wws[i] = 0;       for (i = 0; i < n; i++) wws[wv[i]]++;       for (i = 1; i < m; i++) wws[i] += wws[i - 1];       for (i = n - 1; i >= 0; i--) sa[--wws[wv[i]]] = y[i];       for (t = x, x = y, y = t, p = 1, x[sa[0]] = 0, i = 1; i < n; i++)         x[sa[i]] = cmp(y, sa[i - 1], sa[i], j) ? p - 1 : p++;     }   }   void calheight(int *r, int *sa, int n) {     int i, j, k = 0;     for (i = 1; i <= n; i++) rnk[sa[i]] = i;     for (i = 0; i < n; height[rnk[i++]] = k)       for (k ? k-- : 0, j = sa[rnk[i] - 1]; r[i + k] == r[j + k]; k++)         ;   }   int sa[N], data[N], n;   void Deal() {     DA(data, sa, n + 1, 128);     calheight(data, sa, n);   }   char s[2000002];   int Len;   struct z {     int opn, cls;   };   z Tree[2000002 * 4];   void Update(int id, int l, int r, int pos) {     if (l == r) {       if (s[pos] ==  ( ) {         Tree[id].opn = 1;       } else         Tree[id].cls = 1;       return;     }     int mid = (l + r) / 2;     int lft = 2 * id;     int rgt = lft + 1;     if (pos <= mid) {       Update(lft, l, mid, pos);     } else {       Update(rgt, mid + 1, r, pos);     }     int mn = min(Tree[lft].opn, Tree[rgt].cls);     Tree[id].cls = Tree[lft].cls + Tree[rgt].cls - mn;     Tree[id].opn = Tree[rgt].opn + Tree[lft].opn - mn;     return;   }   z Query(int id, int l, int r, int st, int ed) {     if (st <= l && ed >= r) {       return Tree[id];     }     int mid = (l + r) / 2;     int lft = 2 * id;     int rgt = lft + 1;     if (ed <= mid) {       return Query(lft, l, mid, st, ed);     } else if (st > mid) {       return Query(rgt, mid + 1, r, st, ed);     } else {       z a, b, c;       a = Query(lft, l, mid, st, ed);       b = Query(rgt, mid + 1, r, st, ed);       int mn = min(a.opn, b.cls);       c.cls = a.cls + b.cls - mn;       c.opn = b.opn + a.opn - mn;       return c;     }   }   int dp[2000002], Close[2000002], len, dp1[2000002];   void Solve() {     int Last = -1, Last1 = -1;     for (int i = Len + 1 - 1; i >= 1; i--) {       if (s[i] ==  ) )         Last = -1;       else if (Last == -1) {         Last = i;       }       dp[i] = (Last == -1 ? 0 : (Last - i + 1));       if (s[i] ==  ( )         Last1 = -1;       else if (Last1 == -1) {         Last1 = i;       }       dp1[i] = (Last1 == -1 ? 0 : (Last1 - i + 1));     }   }   int A[4 * 2000002];   void Update(int id, int l, int r, int pos, int val) {     if (l == r) {       A[id] = height[pos];       return;     }     int mid = (l + r) / 2;     int lft = 2 * id;     int rgt = lft + 1;     if (pos <= mid) {       Update(lft, l, mid, pos, val);     } else {       Update(rgt, mid + 1, r, pos, val);     }     A[id] = min(A[lft], A[rgt]);     return;   }   int Lcp(int id, int l, int r, int st, int ed) {     if (st <= l && ed >= r) {       return A[id];     }     int mid = (l + r) / 2;     int lft = 2 * id;     int rgt = lft + 1;     if (ed <= mid) {       return Lcp(lft, l, mid, st, ed);     } else if (st > mid) {       return Lcp(rgt, mid + 1, r, st, ed);     } else {       int a, b;       a = Lcp(lft, l, mid, st, ed);       b = Lcp(rgt, mid + 1, r, st, ed);       return min(a, b);     }   }   int HandleJhamela(int id, int id1, int Opn, int mx) {     int Suru = id + min(len, dp[id]), Suru1 = id1 + min(len, dp[id1]);     int Rnk = rnk[Suru - 1], Rnk1 = rnk[Suru1 - 1];     int L1 = len + mx - Opn - Close[id], L2 = len + mx - Opn - Close[id1];     int f = 0;     if (Rnk > Rnk1) swap(Rnk, Rnk1), f = 1;     int lcp = Lcp(1, 1, n, Rnk + 1, Rnk1);     if (f) swap(Rnk, Rnk1);     if (lcp >= min(L1, L2)) {       int diff = abs(L2 - L1);       if (L1 < L2) {         if (dp1[id1 + min(len, dp[id1]) + lcp] < diff)           return id1;         else           return id;       } else {         if (dp1[id + min(len, dp[id]) + lcp] < diff)           return id;         else           return id1;       }     } else {       if (Rnk < Rnk1)         return id;       else         return id1;     }   }   int main() {     n = 0;     scanf( %s , &s);     len = strlen(s);     for (int i = len + 1 - 1; i >= 1; i--) s[i] = s[i - 1];     Len = len * 2;     for (int i = len + 1; i < Len + 1; i++) s[i] = s[i - len];     Solve();     for (int i = 1; i < Len + 1; i++) {       Update(1, 1, Len, i);       data[n] = (int)s[i];       n++;     }     data[n] = 0;     Deal();     for (int i = 1; i < n; i++) Update(1, 1, n, i, height[i]);     int mx = (1 << 28), Open = 0, Id = 0;     for (int i = 1; i < len + 1; i++) {       z ans = Query(1, 1, Len, i, (i + len - 1));       int Cst = ans.cls + ans.opn;       Close[i] = ans.opn;       int CntOpn = ans.cls + (min(len, dp[i]));       if (mx > Cst) {         mx = Cst;         Open = CntOpn;         Id = i;       } else if (mx == Cst && CntOpn > Open) {         Open = CntOpn;         Id = i;       } else if (mx == Cst && CntOpn == Open) {         Id = HandleJhamela(Id, i, CntOpn, mx);       }     }     for (int i = 0; i < Open; i++) {       printf( ( );     }     int baki = len + mx - Open - Close[Id];     int St = Id + dp[Id];     for (int i = 0; i < baki; i++) {       printf( %c , s[St + i]);     }     for (int i = 0; i < Close[Id]; i++) {       printf( ) );     }     printf(  n );     return 0;   }