• UVA 12219-Common Subexpression Elimination


    原题链接:点击此处

    觉得这题好难呀!方法在紫书上,十一节公共表达式消除那小节(没带书回来,具体页数不清楚啦~)

    这题树中的结点对应的子树都是二叉树,不存在只有一个儿子的情况。输入的字符串中也只有两种情况,结点名字后面紧跟一个左括号的,和不跟括号的。

    因此很容易判断一个结点是否为叶子结点:只要在原字符串中看他后面有没有紧跟着左括号就行了。如果有,立刻递归建树作为左子树。因为有左子树就一定有右子树,所以左子树建完后就可以从字符串中左子树结束的位置开始建右子树了。因此不需要从左到右扫描寻找逗号来分割左右子树。

    另外字符串的对比是缓慢的。鉴于这道题最多只有四个小写字母,也就是最多26*4种情况,我们完全可以用整数来代替字符串。一种比较简单的做法是把字符串看成一个四位的27进制数,并抛弃0,因为0和0000相等。

    代码如下:

    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #include<iostream>
    #include<map>
    #include<stdio.h>
    using namespace std;
    
    void decode(int a) {
        vector<char> result;
        while(a) { result.push_back(a%27+'a'-1); a/=27; }       //%27+1
        for(int i = result.size() - 1; i >= 0; i --) {
            cout<<result[i];
        }
    }
    
    struct Tree {
        int rcode, lch, rch;        //code of root. treeid of left and right sub-tree.
        Tree(){}
        Tree(int a, int b, int c):rcode(a), lch(b), rch(c) { }
        bool operator < (const Tree& rhs) const {
            if(rcode == rhs.rcode){
                if(lch == rhs.lch) return rch < rhs.rch;
                return lch < rhs.lch;
            }
            return rcode < rhs.rcode;
        }
    };
    
    //Global Variables. Reset upon Each Case!
    const int maxn = 50000+5;
    int T, treecnt, vis[maxn], ans[maxn], cnt;
    char str[5*(maxn+10000)], *p;
    Tree trees[maxn];
    map<Tree, int> tree_map;
    /////
    
    int getTreeID(Tree& t)
    {
        if(tree_map.count(t)) return tree_map[t];
        else
        {
            Tree& v = trees[treecnt];
            v = t;
            return tree_map[t] = treecnt++;
        }
    }
    
    int parse()
    {
        int lch = -1, rch = -1;
        int name = 0;
        while(isalpha(*p)) {
            name = name*27 + (*p-'a'+1);
            p ++;
        }
        if(*p == '(') {
            p++;
            lch = parse();
            p ++;
            rch = parse();
            p ++;
        }
        Tree tmp = Tree(name, lch, rch);
        return getTreeID(tmp);
    }
    
    void print_ans(int id)
    {
        if(ans[id] != -1) cout<<ans[id];
        else {
            ans[id] = ++cnt;
            decode(trees[id].rcode);
            if(trees[id].lch != -1)
            {
                cout<<"(";
                print_ans(trees[id].lch);
                cout<<",";
                print_ans(trees[id].rch);
                cout<<")";
            }
        }
    }
    
    int main()
    {
        memset(vis, -1, sizeof(vis));
        cin>>T;
        while(T--)
        {
            treecnt = cnt = 0;
            tree_map.clear();
            scanf("%s", str);
            p = str;
            memset(ans, -1, sizeof(ans));
            print_ans(parse());
            printf("
    ");
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    Android笔记——在布局文件中插入另一个布局文件
    Android在代码中使用布局文件中的一个组件
    Android 判断字符串是否为空
    android .9图的作用
    Android之ViewPager组件实现左右滑动View
    java 字符串判断是否相等
    动态获取R.drawable.xx资源
    解决ViewPager多次刷新后重叠问题
    解决分布式一致性问题 学习2
    解决分布式一致性问题 学习1
  • 原文地址:https://www.cnblogs.com/gdvxfgv/p/5721887.html
Copyright © 2020-2023  润新知