转自:http://blog.csdn.net/xl2015190026/article/details/51927559
题目大意:
见紫书p354
基本思路:
二叉树递归,解决超时问题就用map,虽然我不会写map,这是一个问题;
这个print之所以还是用一个done来标记是因为怕越界,如果用数组就得开的非常大,而且容易越界;
代码如下:
#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//要用map一定要重载运算符。 { 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>MAP;//保存ID map<int,tree>NODE;//保存节点信息 int solve()//只扫描一遍,好棒。 { string cur; while(s[k]>=‘a‘&&s[k]<=‘z‘) cur.push_back(s[k++]); int id=++cnt;//跟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(MAP[t]) {cnt--;return MAP[t];}//如果MAP[t]!=0,那么cnt必为id+1,cnt--即可取消预留的编号。 else return MAP[t]=id; } //原来还可以这样输出。。。不过前两遍的代码我是一遍dfs解决建树与输出的。 //该省的不省。。不该省的乱省。。只能说自己对时间复杂度不够敏感吧。 void print(int u) { if(done[u]) printf("%d",u); else { done[u]=1; cout<<NODE[u].s; if(NODE[u].ls) { cout<<"("; print(NODE[u].ls); cout<<","; print(NODE[u].rs); cout<<")"; } } } int main() { int q; cin>>q; while(q--) { MAP.clear(); done.clear(); NODE.clear(); cnt=k=0; cin>>s; print(solve());//solve返回根编号,print从根标号开始递归输出。 puts(""); } return 0; }