UVA12219

//by Rujia Liu

/*
字符串的对比是缓慢的。
鉴于这道题最多只有四个小写字母,
也就是最多26*4种情况,
我们完全可以用整数来代替字符串。
一种比较简单的做法是把字符串看成一个四位的27进制数,
并抛弃0,因为0和0000相等。
*/

#include<cstdio>
#include<cctype>
#include<string>
#include<map>
using namespace std;

const int maxn = 60000;
int T, kase, cnt;
char expr[maxn*5], *p;
int done[maxn]; 

struct Node { //一个结点存储了
  string s;
  int hash, left, right;
  bool operator < (const Node& rhs) const {  //定义一个全序,用于map
    if(hash != rhs.hash) return hash < rhs.hash;
    if(left != rhs.left) return left < rhs.left;
    return right < rhs.right;
  }
} node[maxn];

map<Node,int> dict;

int parse() {
  int id = cnt++;
  Node& u = node[id];
  u.left = u.right = -1;
  u.s = "";
  u.hash = 0;
  while(isalpha(*p)) {
    u.hash = u.hash * 27 + *p - ‘a‘ + 1;
    u.s.push_back(*p);
    p++;
  }
  if (*p == ‘(‘) { // (L,R)
    p++; u.left = parse(); p++; u.right = parse(); p++;
  }
  if (dict.count(u) != 0) {
  //先建好一个结点,然后看这个结点是不是已经有了,如果有了这个结点就不必建了
    cnt--;
    return dict[u];
  }
  return dict[u] = id;
}

void print(int v) {  //打印结果,kase用于标记
  if(done[v] == kase)
    printf("%d", v + 1);
  else {
    done[v] = kase;
    printf("%s", node[v].s.c_str());
    if(node[v].left != -1) {
      putchar(‘(‘);
      print(node[v].left);
      putchar(‘,‘);
      print(node[v].right);
      putchar(‘)‘);
    }
  }
}

int main() {
  scanf("%d", &T);
  for(kase = 1; kase <= T; kase++) {
    dict.clear();
    cnt = 0;
    scanf("%s", expr);
    p = expr;
    print(parse());
    putchar(‘\n‘);
  }
  return 0;
}
时间: 2025-01-12 04:09:46

UVA12219的相关文章

UVa12219 Common Subexpression Elimination (表达式树)

链接:http://vjudge.net/problem/UVA-12219 分析:用一个map把子树映射成编号1,2,....这样一来,一棵子树就可以用三元组(s,left,right)表示(s表示根结点字符串,left,right表示左右子结点编号).这样,每次判断一棵子树是否出现过只需要在map中查找,总时间复杂度为O(nlogn). 1 #include <cstdio> 2 #include <string> 3 #include <map> 4 using

uva-12219

https://vjudge.net/problem/UVA-12219 思路:把每一个子树用一个数代替放到map里,这样查一棵子树是否出现就是快多了.递归打印答案即可. #include<bits/stdc++.h> #define _for(i,a,b) for(int i=a;i<=b;i++) using namespace std; typedef long long ll; const int mod =1e6+7; double esp=1e-6; int INF =0x3

例题11-1 公共表达式消除 UVa12219

1.题目描述:点击打开链接 2.解题思路:第一步是构造表达式树,构造时可以利用一个map来记录出现的子树,并为之编号.例如,用(a,0,0)可以表示一个叶子a,用(b,3,6)表示根的名字是b,子树的编号分别是3,6的树.这样既可方便地得到最简表达式.本题总的时间复杂度为O(N*logN). 3.代码: #define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<algorithm> #include<string&

第11章 图论模型与算法

再谈树 无根树转有根数 #include<bits/stdc++.h> using namespace std; const int maxn = 100; vector<int> G[maxn]; int n; void read_tree(){ int u,v; scanf("%d",&n); for(int i=0;i<n-1;i++){ scanf("%d%d",&u,&v); G[u].push_bac