#include <iostream>
#include <vector>
#include <deque>
#include <string>
using namespace std;
// 定义并查集类
class UnionFindSet {
public:
vector<int> fa; // 存储每个节点的父节点
int count; // 当前连通块的数量
UnionFindSet(int n) : count(n) { // 构造函数,初始化父节点为自身
fa.resize(n);
for (int i = 0; i < n; i++) fa[i] = i;
}
int find(int x,int mnum) { // 查找节点的根节点
if (x != fa[x]) {
fa[x] = find(fa[x],min(mnum,fa[x])); // 路径压缩
}
fa[x]=min(mnum,fa[x]);
return fa[x];
}
void unionSet(int x, int y) { // 合并两个节点所在的连通块
int x_fa = find(x,fa[x]);
int y_fa = find(y,fa[y]);
if (x_fa != y_fa) { // 如果两个节点不在同一个连通块中,则合并
fa[max(x_fa,y_fa)] = min(x_fa,y_fa); // 将y所在的连通块合并到x所在的连通块中
count--; // 连通块数量减1
}
}
};
int main() {
UnionFindSet s(150);
vector<int> is(150,0);
string str;
deque<int> q1,q2;
cin >> str;
int temp=0;
for(char c:str){
if(c=='('){
temp=1;
}
else if(c==')'){
temp=0;
int i;
if(!q2.empty()){
i=q2.front();
}
while(!q2.empty()){
s.unionSet(i, q2.front());
is[q2.front()]=1;
if(q2.front()>='a'){
if(is[q2.front()-'a'+'A']==1)
s.unionSet(q2.front()-'a'+'A', q2.front());
}
else{
if(is[q2.front()+'a'-'A']==1)
s.unionSet(q2.front()+'a'-'A', q2.front());
}
q2.pop_front();
}
}
else if(temp==0){
q1.push_back(c);
}
else{
q2.push_back(c);
}
}
if(q1.empty())
cout <<0;
while(!q1.empty()){
cout << char(s.find(q1.front(),q1.front()));
q1.pop_front();
}
return 0;
}