紫書 例題11-1 公共表達式消除 UVa12219 表達式樹,遞歸


題目鏈接: 點這里

題意: 可以參考紫書P354 - P355。

解題方法:第一步是構造表達式樹,構造時可以利用一個map來記錄出現的子樹,並為之編號。例如,用(a,0,0)可以表示一個葉子a,用(b,3,6)表示根的名字是b,子樹的編號分別是3,6的樹。這樣既可方便地得到最簡表達式。本題總的時間復雜度為O(N*logN)。具體細節在代碼中也有詳細描述。

代碼如下:

//
//Created by BLUEBUFF 2016/1/29
//Copyright (c) 2016 BLUEBUFF.All Rights Reserved
//

#pragma comment(linker,"/STACK:102400000,102400000")
//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/tree_policy.hpp>
//#include <ext/pb_ds/hash_policy.hpp>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <cmath>
#include <cstdio>
#include <time.h>
#include <cstdlib>
#include <cstring>
#include <complex>
#include <sstream> //isstringstream
#include <iostream>
#include <algorithm>
using namespace std;
//using namespace __gnu_pbds;
typedef long long LL;
typedef unsigned long long uLL;
typedef pair<int, LL> pp;
#define REP1(i, a, b) for(int i = a; i < b; i++)
#define REP2(i, a, b) for(int i = a; i <= b; i++)
#define REP3(i, a, b) for(int i = a; i >= b; i--)
#define CLR(a, b) memset(a, b, sizeof(a))
#define MP(x, y) make_pair(x,y)
template <class T1, class T2>inline void getmax(T1 &a, T2 b) { if (b>a)a = b; }
template <class T1, class T2>inline void getmin(T1 &a, T2 b) { if (b<a)a = b; }
const int maxn = 60010;
const int maxm = 1e5+5;
const int maxs = 10;
const int maxp = 1e3 + 10;
const int INF = 1e9;
const int UNF = -1e9;
const int mod = 1e9 + 7;
const int rev = (mod + 1) >> 1; // NTT
//const double PI = acos(-1);
//head
int T, ks, cnt;
int vis[maxn];
char expr[maxn * 5], *p;
struct node{
string s;
int val, left, right;
node(){}
node(string s, int val, int left, int right) : s(s), val(val), left(left), right(right){}
bool operator <(const node &rhs) const{ //重載小於運算符
if(val != rhs.val) return val < rhs.val;
if(left != rhs.left) return left < rhs.left;
return right < rhs.right;
}
}tree[maxn];
map <node, int> mp; //映射子樹的編號
int work(){
int id = cnt++; //編號從0開始
node &u = tree[id];
u.left = u.right = -1, u.s = "", u.val = 0;
while(isalpha(*p)){
u.val = u.val * 27 + *p - 'a' + 1;
u.s.push_back(*p);
p++;
}
if(*p == '('){
p++; //先跳過'('
u.left = work(), p++; //返回左子樹編號,並跳過','
u.right = work(), p++; //返回右子樹編號,並跳過')'
}
if(mp.count(u)){
cnt--;//子樹出現過,個數減少1
return mp[u];//返回這顆子樹的編號
}
return mp[u] = id;
}
void print(int v){
if(vis[v] == ks){
printf("%d", v + 1);
}
else{
vis[v] = ks;//不需要對vis數組初始化,只需要用這一輪特有的ks標記即可
printf("%s", tree[v].s.c_str());
if(tree[v].left != -1){
putchar('(');
print(tree[v].left);
putchar(',');
print(tree[v].right);
putchar(')');
}
}
}
int main(){
scanf("%d", &T);
for(ks = 1; ks <= T; ks++){
mp.clear();
cnt = 0;
scanf("%s", expr);
p = expr;
print(work());
putchar('\n');
}
return 0;
}

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com