Common Subexpression Elimination UVA - 12219(表达式树)

传送门

题意:不好描述,总结而言,就是消除公共表达式

题解:使用表达式树,然后再建造表达式树的时候,因为要看后面的子树是否前面出现过,可以使用"集合栈计算机"的思想,利用一个map存储当前字符和两个值存储左儿子编号和右儿子编号,都压入map中进行比较,最后再利用个done数组判断这个子树是否已经输出过,没有输出过输出字符,输出过输出结点编号即可。

有关表达式树的介绍:

二叉树是表达式处理的有效工具,例如表达a+b*(c-d)-e/f,每个非叶节点表示一个运算符,可以利用“找到最后计算"的运算符进行递归处理。

附上代码:

const int maxn=1e3+5;

int lch[maxn],rch[maxn];
char op[maxn];
int nc=0;

int build(char *s,int x,int y)
{
    int i,c1=-1,c2=-1,p=0;
    int u;
    if(y-x==1){//仅一个字符,建立单独结点
        u=++nc;
        lch[u]=rch[u]=0;
        op[u]=s[x];
        return u;
    }
    for(i=x;i<y;i++){
        switch(s[i]){
            case '(':p++;break;
            case ')':p--;break;
            case '+':case '-':if(!p)c1=i;break;
            case '*':case '/':if(!p)c2=i;break;
        }
    }
    if(c1<0){//找不到括号外的加减号,就用乘除号
        c1=c2;
    }
    if(c1<0){//整个表达式被一对括号括起来
        return build_tree(s,x+1,y-1);
    }
    u=++nc;
    lch[u]=build_tree(s,x,c1);
    rch[u]=build_tree(s,c1+1,y);
    op[u]=s[c1];
    return u;
}

如何寻找最后一个运算符,先找括号外面的,如果没有去掉括号继续找。

附上本题代码:


#include<bits/stdc++.h>

using namespace std;

const int maxn=6e4+50;

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{
        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) {
  if(done[v] == kase)
    printf("%d", v + 1);
  else {
    done[v] = kase; // 常见小技巧,可以避免memset(done, 0, sizeof(done))
    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;
}

猜你喜欢

转载自blog.csdn.net/zhouzi2018/article/details/84923192