12219 - Common Subexpression Elimination(表达式树)

草草刷了一下暴力,开始转战图论了。   这是第一道例题,讲解了一种实用而神奇的树状结构:表达式树 。虽然打比赛从来没见过,但是我练这个本来也不只是为了比赛 , 重要的是ACM本身带给我的乐趣 。

该题的一个很巧妙的做法是将每一个结点用一个三元组来表示,然后映射到map中以去重 。 其中三元组中有一个string , 我们可以用hash来处理这个string 。

因为string最大长度为4, 所以我们可以这样处理 : int hash = 0;    hash = hash * 27 + s[i] - ‘0‘ + 1;

将hash每次乘以27 是因为字符串只有小写字母,这样做可以完美的去重 ,保证了哈希表不会重复 。

细节参见代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 60000;
int T,n,m,kase,cnt,done[maxn];
char s[maxn*5],*p;
struct node {
    string s;
    int hash,l,r;
    bool operator < (const node& u) const {
        if(hash != u.hash) return hash < u.hash;
        if(l != u.l) return l < u.l;
        return r < u.r;
    }
}nodes[maxn];
map<node,int> dict;
int parse() {
    int id = cnt++;
    node& u = nodes[id];
    u.l = u.r = -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 == '(') {
        p++; u.l = parse(); p++; u.r = parse(); p++;
    }
    if(dict.count(u)) {
        id--; cnt--;
        return dict[u];
    }
    return dict[u] = id;
}
void print(int v) {
    if(done[v] == kase) printf("%d",v+1);
    else {
        done[v] = kase;
        printf("%s",nodes[v].s.c_str());
        if(nodes[v].l != -1) {
            printf("(");
            print(nodes[v].l); //递归求得结点值并打印 。
            printf(",");
            print(nodes[v].r);
            printf(")");
        }

    }
}
int main() {
    scanf("%d",&T);
    for(kase = 1; kase <= T; ++kase) {
        dict.clear();
        cnt = 0;
        scanf("%s",s);
        p = s;
        print(parse());
        printf("\n");
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-07-29 08:29:21

12219 - Common Subexpression Elimination(表达式树)的相关文章

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

LinqToDB 源码分析——生成表达式树

当我们知道了Linq查询要用到的数据库信息之后.接下就是生成对应的表达式树.在前面的章节里面笔者就已经介绍过.生成表达式树是事实离不开IQueryable<T>接口.而处理表达式树离不开IQueryProvider接口.LinqToDB框架跟这俩个接口有关系的有三个类:Table<T>类.ExpressionQuery<T>类.ExpressionQueryImpl<T>类.其中最重要的是ExpressionQuery<T>类.他是Table&l

C#中的表达式树的浅解

表达式树可以说是Linq的核心之一,为什么是Linq的核心之一呢?因为表达式树使得c#不再是仅仅能编译成IL,我们可以通过c#生成一个表达式树,将结果作为一个中间格式,在将其转换成目标平台上的本机语言.比如SQL.我们常用的Linq to sql就是这样生成SQL的. 表达式树是.NET 3.5之后引入的,它是一个强大灵活的工具(比如用在LINQ中构造动态查询). 先来看看Expression类的API接口: namespace System.Linq.Expressions { // // 摘

关于Expression表达式树的拼接

最近在做项目中遇到一个问题,需求是这样的: 我要对已经存在的用户进行检索,可以根据用户的id 或者用户名其中的一部分字符来检索出来,这样就出现了三种情况 只有id,只有用户名中一部字符,或者全部都有. 我们用的MVC+EF5.0的框架,在BLL层进行查询的 时候需要构建lambda表达式来作为查询条件,但是,我们怎么来构建lambda来确定查询的条件呢?我们知道Express<Func<T,bool>>这样的一个参数可以是lambda表达式,但是这里的按条件拼接式不能使用委托链的形

[.net 面向对象程序设计进阶] (5) Lamda表达式(二) 表达式树快速入门

[.net 面向对象程序设计进阶] (6) Lamda表达式(二) 表达式树快速入门 本节导读: 认识表达式树(Expression Tree),学习使用Lambda创建表达式树,解析表达式树. 学习表达式在程序设计中的优点:比如构造动态查询.动态构造表达式树完成未知对象属性访问,比反射的性能高出很多.我们可以说表达式树才是Lambda的精髓,是我们必须要熟练掌握并灵活运用的. 1.关于表达式树(Expression Tree) 表达式树以树形数据结构表示代码,其中每一个节点都是一种表达式,比如

Lambda表达式和表达式树

在C# 2.0中,通过方法组转换和匿名方法,使委托的实现得到了极大的简化.但是,匿名方法仍然有些臃肿,而且当代码中充满了匿名方法的时候,可读性可能就会受到影响.C# 3.0中出现的Lambda表达式在不牺牲可读性的前提下,进一步简化了委托. LINQ的基本功能就是创建操作管道,以及这些操作需要的任何状态.这些操作表示了各种关于数据的逻辑,例如数据筛选,数据排序等等.通常这些操作都是用委托来表示.Lambda表达式是对LINQ数据操作的一种符合语言习惯的表示方式. Lambda表达式不仅可以用来创

C#秘密武器之表达式树

一.表达式树入门 Lambda表达式树很复杂,从概念上很难理解清楚,一句话,表达式树是一种数据结构!这里我们通过下面的这个例子来理解一下表达式树,你就能看个大概: lambda表达式树动态创建方法 static void Main(string[] args) { //i*j+w*x ParameterExpression a = Expression.Parameter(typeof(int),"i"); //创建一个表达式树中的参数,作为一个节点,这里是最下层的节点 Paramet

用C#表达式树优雅的计算24点

思路:一共4个数字,共需要3个运算符,可以构造一个二叉树,没有子节点的节点的为值,有叶子节点的为运算符 例如数字{1, 2, 3, 4},其中一种解的二叉树形式如下所示: 因此可以遍历所有二叉树可能的形式,4个数的全排列,从4种运算符中挑选3种运算符(运算符可以重复) 核心步骤1:需要遍历所有二叉树的可能,参考Eric Lippert的方法 class Node { public Node Left { get; private set; } public Node Right { get; p

表达式树基础代码

using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using System.Linq.Expressions; namespace TestExpressionLambda { class ProgramExpression { static void Main(st