表达式树(公共表达式消除 uva 12219)

2.解题思路:第一步是构造表达式树,构造时可以利用一个map来记录出现的子树,并为之编号。例如,用(a,0,0)可以表示一个叶子a,用(b,3,6)表示根的名字是b,子树的编号分别是3,6的树。这样既可方便地得到最简表达式。本题总的时间复杂度为O(N*logN)。

 

#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
    {
        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>tu;
map<int,tree>node;

int solve()
{
    string cur;
    while(s[k]>='a'&&s[k]<='z') cur.push_back(s[k++]);
    int id=++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(tu[t]) {
            cnt--;
    return tu[t];
    }
    else return tu[t]=id;
}
void print(int u)
{
    if(done[u]) printf("%d",u);
    else
    {
        done[u]=1;
        //printf("%d",node[u].s);
        cout<<node[u].s;
        if(node[u].ls)
        {
            printf("(");
            print(node[u].ls);
            printf(",");
            print(node[u].rs);
            printf(")");
        }
    }
}

int main()
{
    int q;
    scanf("%d",&q);
    while(q--)
    {
        tu.clear();
        done.clear();
        node.clear();
        cnt=k=0;
        cin>>s;
        print(solve());
        printf("");
    }
    return 0;
}

 

posted @ 2017-12-31 00:08  lmjer  阅读(339)  评论(0编辑  收藏  举报