Let the set Σ consist of all words composed of 1-4 lower case letters, such as the words "a", "b", "f", "aa", "fun" and "kvqf". Consider expressions according to the grammar with the two rules
E -> f
E -> f(E, E)
for every symbol f ∈ Σ. Any expression can easily be represented as a tree according to its syntax.
For example, the expression "a(b(f(a,a),b(f(a,a),f)),f(b(f(a,a),b(f(a,a),f)),f))" is represented by he tree on the left in the following figure:

Last night you dreamt of a great invention which considerably reduces the size of the representation:
use a graph instead of a tree, to share common subexpressions. For example, the expression above can be represented by the graph on the right in the figure. While the tree contains 21 nodes, the graph just contains 7 nodes.
Since the tree on the left in the figure is also a graph, the representation using graphs is not necessarily unique. Given an expression, find a graph representing the expression with as few nodes as possible!
E -> f(E, E)
for every symbol f ∈ Σ. Any expression can easily be represented as a tree according to its syntax.
For example, the expression "a(b(f(a,a),b(f(a,a),f)),f(b(f(a,a),b(f(a,a),f)),f))" is represented by he tree on the left in the following figure:

Last night you dreamt of a great invention which considerably reduces the size of the representation:
use a graph instead of a tree, to share common subexpressions. For example, the expression above can be represented by the graph on the right in the figure. While the tree contains 21 nodes, the graph just contains 7 nodes.
Since the tree on the left in the figure is also a graph, the representation using graphs is not necessarily unique. Given an expression, find a graph representing the expression with as few nodes as possible!
Input
The first line of the input contains the number c (1 <= c <= 200), the number of expressions. Each of the following c lines contains an expression according to the given syntax, without any whitespace.
Its tree representation contains at most 50 000 nodes.
Its tree representation contains at most 50 000 nodes.
Output
For each expression, print a single line containing a graph representation with as few nodes as possible.
The graph representation is written down as a string by replacing the appropriate subexpressions with numbers. Each number points to the root node of the subexpression which should be inserted at that position. Nodes are numbered sequentially, starting with 1; this numbering includes just the nodes of the graph (not those which have been replaced by numbers). Numbers must point to nodes written down before (no forward pointers). For our example, we obtain "a(b(f(a,4),b(3,f)),f(2,6))".
The graph representation is written down as a string by replacing the appropriate subexpressions with numbers. Each number points to the root node of the subexpression which should be inserted at that position. Nodes are numbered sequentially, starting with 1; this numbering includes just the nodes of the graph (not those which have been replaced by numbers). Numbers must point to nodes written down before (no forward pointers). For our example, we obtain "a(b(f(a,4),b(3,f)),f(2,6))".
Sample Input
3
this(is(a,tiny),tree) a(b(f(a,a),b(f(a,a),f)),f(b(f(a,a),b(f(a,a),f)),f)) z(zz(zzzz(zz,z),zzzz(zz,z)),zzzz(zz(zzzz(zz,z),zzzz(zz,z)),z))
Sample Output
this(is(a,tiny),tree) a(b(f(a,4),b(3,f)),f(2,6)) z(zz(zzzz(zz,z),3),zzzz(2,5))这题和普通的表达式树很像,但如果按照一般的做法(用L、R代表范围),会TLE,因为重复了太多无用的扫描
这题树中的结点对应的子树都是二叉树,不存在只有一个儿子的情况。输入的字符串中也只有两种情况,结点名字后面紧跟一个左括号的,和不跟括号的。
因此很容易判断一个结点是否为叶子结点:只要在原字符串中看他后面有没有紧跟着左括号就行了。如果有,立刻递归建树作为左子树。因为有左子树就一定有右子树,所以左子树建完后就可以从字符串中左子树结束的位置开始建右子树了。因此不需要从左到右扫描寻找逗号来分割左右子树。
另外字符串的对比是缓慢的。鉴于这道题最多只有四个小写字母,也就是最多26*4种情况,我们完全可以用整数来代替字符串。一种比较简单的做法是把字符串看成一个四位的27进制数,并抛弃0,因为0和0000相等。
代码:
//#include <bits/stdc++.h> #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <set> #include <map> #include <vector> using namespace std; void decode(int a) //将27进制转换回字符 { vector<char> result; while(a){result.push_back(a%27+'a'-1); a/=27;} for(int i = result.size()-1; i>=0; i--) { cout << result[i]; } } struct Tree { int rcode, lch, rch; //根左右 Tree(){} Tree(int a, int b, int c): rcode(a),lch(b),rch(c){} bool operator < (const Tree& rhs)const{ if(rcode == rhs.rcode) { if(lch == rhs.lch) { return rch < rhs.rch; } return lch < rhs.lch; } return rcode < rhs.rcode; } }; const int maxn = 50000+5; char str[5*(maxn+10000)], *p; //输入的字符串和遍历它用的指针 map<Tree, int> tree_map; //每个根映射一个27进制int Tree trees[maxn]; int T, treecnt, vis[maxn], ans[maxn], cnt; int getTreeID(Tree& t) //给树编号 { if(tree_map.count(t)) return tree_map[t]; else { Tree& v = trees[treecnt]; v = t; return tree_map[t] = treecnt++; } } int build_tree() //递归建树 { int lch = -1, rch = -1; int name = 0; while(isalpha(*p)) { //转换为27进制 name = name*27 + (*p-'a'+1); p++; } if(*p == '(') { p++; lch = build_tree(); p++; rch = build_tree(); p++; } Tree temp = Tree(name,lch,rch); return getTreeID(temp); } void print_ans(int id) //递归输出结果 { if(ans[id] != -1) cout << ans[id]; else { ans[id] = ++cnt; decode(trees[id].rcode); if(trees[id].lch != -1) { cout << "("; print_ans(trees[id].lch); cout << ","; print_ans(trees[id].rch); cout << ")"; } } } int main() { //freopen("in.txt", "r", stdin); int T; scanf("%d", &T); memset(vis, -1, sizeof(vis)); while(T--) { treecnt = cnt = 0; tree_map.clear(); scanf("%s", str); p = str; memset(ans, -1 ,sizeof(ans)); print_ans(build_tree()); cout << endl; } return 0; }