判断相同的子树--uva12219 Common Subexpression Elimination

给定一棵树,第一次出现的结点直接输出,并编号。如果有重复的子树,就输出该子树的根的编号。

//非常神奇的递归

#include <iostream>

#include <cstdio>

#include <map>

#include <string>

using namespace std;

const int maxn = 5e4 + 5;

char line[maxn << 3],*p;

int cn = 0;

int cnt = 0;

int done[maxn];//该结点是否已输出,即第一次输出串,之后输出数字

struct Node{

    string s;

    int rt,lc,rc;

    bool operator < (const Node &a) const{

        if(rt != a.rt) return rt < a.rt;

        if(lc != a.lc) return lc < a.lc;

        return rc < a.rc;

    }

}node[maxn];

map<Node,int> mp;

int parse()

{

    int id = cnt ++;

    Node &u = node[id];

    u.lc = u.rc = -1;

    u.s = "";

    u.rt = 0;

    while (isalpha(*p)) {

        u.rt = u.rt * 27 + *p - 'a' + 1;

        u.s += *p;

        p ++;

    }

    if(*p == '('){//(L,R)

        p ++;u.lc = parse();p ++;u.rc = parse();p ++;

    }

    if(mp.find(u) != mp.end()){

        id --,cnt --;

        return mp[u];

    }

    return mp[u] = id;

}

void print(int v)

{

    if(done[v] == cn){

        printf("%d",v + 1);

    }

    else{

        done[v] = cn;//避免memset

        printf("%s",node[v].s.c_str());

        if(node[v].lc != -1){

            putchar('(');

            print(node[v].lc);

            putchar(',');

            print(node[v].rc);

            putchar(')');

        }

    }

}

int main()

{

    int T;

    scanf("%d%*c",&T);

    for(cn = 1;cn <= T;cn ++) {

        scanf("%s",line);

        mp.clear();

        cnt = 0;

        p = line;

        print(parse());

        putchar('\n');

    }

    return 0;

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值