表达式树(公共表达式消除 uva 12219)
来源:互联网 发布:js通过标签名获取元素 编辑:程序博客网 时间:2024/05/02 00:53
一共写了3遍,2遍超时,第三遍看了别人的代码才写出来的。。。
第一遍,直接保存整颗子树,也就是整个子表达式。
为了得到子表达式的值,我频繁调用substr函数。
为了找到分隔左右子表达式的逗号,我直接遍历子表达式。
最后用map去映射。
结果超时。。
后来看了下紫书,说不能保存整颗子树。。
说比较两棵树的时间复杂度是O(n),循环枚举两颗子树,总时间复杂度高达O(n^3)。
我本以为map比较高效的,但后来我仔细算了下发现不会高效很多。
我们都知道map的时间复杂度是O(logn),但是那只是查询的复杂度。如果你查询的是字符串,那就多O(n),每个子树查询一遍,就又多O(n),总共O(n^2logn)。
伤不起。。。
第二遍,建树使扫描整个子表达式找到中间的那个逗号
按书上说的改了下子树的保存方式后,时间复杂度变为O(nlogn),依旧超时。
后来上网看别人的代码,才知道我建树的方法太粗暴了。频繁调运substr+遍历找逗号,都不知道循环多少遍了。
只有扫描一遍的才不会超时。
参考 http://www.bubuko.com/infodetail-646757.html
AC代码
#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;//保存IDmap<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;}
第一遍代码
#include<stdio.h>#include<iostream>#include<string>#include<map>using namespace std;struct tree{ string now; int l,r; tree(string a,int b,int c):now(a),l(b),r(c){}};map<string,int>MAP;string s;int cnt;void dfs(int l,int r){ string a=s.substr(l,r-l+1); if(MAP[a]) {printf("%d",MAP[a]);return;} int now=++cnt; if(s[r]!=')') {cout<<a;MAP[a]=cnt;return;} while(s[l]!='(') printf("%c",s[l++]); int k=l; int p=0; while(1) { if(s[k]=='(') p++; if(s[k]==')') p--; if(p==1&&s[k]==',') break; k++; } printf("("); dfs(l+1,k-1); printf(","); dfs(k+1,r-1); printf(")"); MAP[a]=now;}int main(){ int c; scanf("%d",&c); while(c--) { MAP.clear(); cnt=0; cin>>s; dfs(0,s.size()-1); puts(""); } return 0;}
第二遍代码
#include<stdio.h>#include<iostream>#include<string>#include<sstream>#include<map>using namespace std;struct tree{ string now; int l,r; tree(string a,int b,int c):now(a),l(b),r(c){} bool operator < (const tree & rhs) const { if(now!=rhs.now) return now<rhs.now; else if(l!=rhs.r) return l<rhs.l; else return r<rhs.r; }};typedef pair<int,int> pii;typedef pair<int,string> pis;map<tree,int>MAP;string s;int cnt;pair<pis,int> dfs(int l,int r){ if(s[r]==')') { int ll=l; while(s[ll]!='(') ll++; int k=ll; int p=0; while(1) { if(s[k]=='(') p++; if(s[k]==')') p--; if(p==1&&s[k]==',') break; k++; } int now=++cnt; string cur=s.substr(l,ll-l); stringstream sss; string ss; pair<pis,int> ls=dfs(ll+1,k-1); pair<pis,int> rs=dfs(k+1,r-1); //cout<<" "<<ls.first.second<<" "<<rs.first.second; tree t=tree(cur,ls.second,rs.second); int id=MAP[t]; if(ls.first.first&&rs.first.first&&id) { cnt--; sss<<id; sss>>ss; return make_pair(make_pair(1,ss),id); } else { sss<<cur; MAP[t]=now; sss<<"("; sss<<ls.first.second; sss<<","; sss<<rs.first.second; sss<<")"; sss>>ss; return make_pair(make_pair(0,ss),now); } } else { string ss=s.substr(l,r-l+1); tree t(ss,0,0); int id=MAP[t]; stringstream sss; if(id) sss<<id; else {MAP[t]=++cnt;sss<<ss;} sss>>ss; if(id) return make_pair(make_pair(1,ss),id); else return make_pair(make_pair(0,ss),cnt); }}int main(){ int c; scanf("%d",&c); while(c--) { MAP.clear(); cnt=0; cin>>s; cout<<dfs(0,s.size()-1).first.second; puts(""); } return 0;}
1 0
- 表达式树(公共表达式消除 uva 12219)
- UVA12219 公共表达式消除 表达式树的建立应用
- 例题11-1 公共表达式消除 UVa12219
- 紫书 例题11-1 公共表达式消除 UVa12219 表达式树,递归
- 公共表达式
- UVA 12219 Common Subexpression Elimination(表达式树)
- UVa 12216 表达式树,map(不会)
- SQL的公共表达式(CTE)
- 消除空格的正则表达式
- db2 公共表达式
- hash 表达式树 UVa 12219 Common Subexpression Elimination
- WITH公共表达式的使用
- UVa Problem 10157 Expressions (括号表达式)
- UVA 14234 表达式
- 百度笔试之消除表达式方括号
- 消除空白行^\s*\n,正则表达式
- Lambda表达式表达式树
- 表达式与表达式树
- scala基础6-lazy 懒执行特性
- BMP图像的处理(24位转16位)
- hibernate缓存机制
- LeetCode--No.144--Binary Tree Preorder Traversal
- 两个栈实现一个队列,两个队列实现一个栈
- 表达式树(公共表达式消除 uva 12219)
- Python读取文件
- Android获取屏幕宽高
- 【解决】Ubuntu无法识别U盘分区(NTFS移动硬盘无法挂载)
- SGU 476 Coach's Trouble(集合独立性、容斥、高精度)
- 对于父类的私有属性,子类是从哪里访问到的?
- Android Art Hook 技术方案
- nginx php问题集
- 折半查找(二分法)