2.解题思路:第一步是构造表达式树,构造时可以利用一个map来记录出现的子树,并为之编号。例如,用(a,0,0)可以表示一个叶子a,用(b,3,6)表示根的名字是b,子树的编号分别是3,6的树。这样既可方便地得到最简表达式。本题总的时间复杂度为O(N*logN)。
#include<stdio.h>
#include<iostream>
#include<map>
#include<string.h>
#include<string>
using namespace std;
string s;
int k,cnt;
map<int,int>done;
struct tree
{
string s;
int ls,rs;
bool operator < (const tree& rhs) const
{
if(s!=rhs.s) return s<rhs.s;
else if(ls!=rhs.ls) return ls<rhs.ls;
else return rs<rhs.rs;
}
};
map<tree,int>tu;
map<int,tree>node;
int solve()
{
string cur;
while(s[k]>='a'&&s[k]<='z') cur.push_back(s[k++]);
int id=++cnt;
tree& t=node[id];
t.s=cur;
t.ls=0;
t.rs=0;
if(s[k]=='(')
{
k++;
t.ls=solve();k++;
t.rs=solve();k++;
}
if(tu[t]) {
cnt--;
return tu[t];
}
else return tu[t]=id;
}
void print(int u)
{
if(done[u]) printf("%d",u);
else
{
done[u]=1;
//printf("%d",node[u].s);
cout<<node[u].s;
if(node[u].ls)
{
printf("(");
print(node[u].ls);
printf(",");
print(node[u].rs);
printf(")");
}
}
}
int main()
{
int q;
scanf("%d",&q);
while(q--)
{
tu.clear();
done.clear();
node.clear();
cnt=k=0;
cin>>s;
print(solve());
printf("");
}
return 0;
}