1. 程式人生 > >(表示式樹)【UVa-12219】Common Subexpression Elimination

(表示式樹)【UVa-12219】Common Subexpression Elimination

陣列開小了RE了一發,日常膜LRJ.

學到倆知識點,一個是結構體作為map或set的key時,需過載<運算子。第二個是直接判斷done[v]==T可以避免一次memset,優化時間。

/*
* @Author: SamsonHo
* @Date:   2018-09-20-12.48.32
* @URL:https://vjudge.net/problem/UVA-12219
*/
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
const int MAXN = 1e5+10;
int T,done[MAXN],cnt;
char str[3*MAXN],*p;

struct Node
{
    string s;
    int h,left,right;
    bool operator < (const Node& rhs) const
    {
    if(h != rhs.h) return h < rhs.h;
    if(left != rhs.left) return left < rhs.left;
    return right < rhs.right;
    }
}node[MAXN];
map<Node,int> dict;

int solve()
{
    int id = cnt++;
    Node& u = node[id];
    u.left = u.right = -1;
    u.s = "";   u.h = 0;
    while(isalpha(*p))
    {
        u.h = u.h*27+*p-'a'+1;
        u.s.push_back(*p);
        ++p;
    }
    if(*p == '(')
    {
        ++p;
        u.left = solve();
        ++p;
        u.right = solve();
        ++p;
    }
    if(dict[u] != 0)
    {
        --cnt;
        --id;
        return dict[u];
    }
    return dict[u] = id;
}

void print(int v)
{
    if(done[v] == T)
    {
        printf("%d",v+1); //避免memset
    }
    else
    {
        done[v] = T;
        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(void)
{
    scanf("%d",&T);
    while(T--)
    {
        dict.clear();
        cnt = 0;
        scanf("%s",str);
        p = str;
        print(solve());
        puts("");
    }
}