一、题目链接

  http://codeforces.com/gym/100198/problem/G

二、题意

  看样例就能明白,写表达式解析器。

三 、思路

  一看这题目,立马就会想到“后缀表达式”,考虑到这里有变量,在把中缀表达式变为后缀表达式时,把变量替换成常量即可。注意,define 2 3 表示,下面的2用3来替换。和C语言是一样的。

PS:然而,我用Java写的,总是RE在第四个样例,实在找不到哪里抛异常了。各位同行,如果您能找到我的代码的bug,烦请您在评论区留下出bug的样例。谢谢!

四、源代码

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.Stack;

public class Main {
    static final String digitPattern = "-?\\d+";
    static final File fin = new File("plcool.in");
    static final File fout = new File("plcool.out");
    static String input;
    static ArrayList<String> inExp = new ArrayList<String>();
    static ArrayList<String> postExp = new ArrayList<String>();
    static Map<Character, Integer> prior = new HashMap<Character, Integer>();
    static Map<String, String> define = new HashMap<String, String>();
    static InputStream is = null;
    static PrintStream ps = null;
    static {
        prior.put('^', 3);
        prior.put('*', 2);
        prior.put('/', 2);
        prior.put('%', 2);
        prior.put('+', 1);
        prior.put('-', 1);
        prior.put('(', 0);
        prior.put(')', 0);
    }

    static String findRoot(String key) {
        if(!define.containsKey(key))return key;
        else return findRoot(define.get(key));
    }

    static int power(int x, int y) {
        int res = 1;
        while(y > 0) {
            if((y & 1) == 1)res *= x;
            x = x * x;
            y >>= 1;
        }
        return res;
    }

    static int mod(int x, int y) {
        int sign = ((x >>> 31) ^ (y >>> 31)) == 0 ? 1 : -1;
        return (Math.abs(x) % Math.abs(y)) * sign;
    }

    static void split() {
        inExp.clear();
        int s = 0, t = 0, len = input.length();
        boolean befOper = false;
        for (int i = 0; i < len; ++i) {
            if(Character.isDigit(input.charAt(i)) || (input.charAt(i) == '-' && (befOper || i == 0))) {
                for(s = i++;i < len && Character.isDigit(input.charAt(i)); ++i);
                inExp.add(input.substring(s, i));
                --i;
                befOper = false;
            }
            else if(Character.isLetter(input.charAt(i))) {
                for(s = i;i < len && (Character.isLetter(input.charAt(i))
                        || Character.isDigit(input.charAt(i))); ++i);
                inExp.add(input.substring(s, i));
                --i;
            }
            else if(prior.containsKey(input.charAt(i))) {
                inExp.add(input.charAt(i) + "");
                befOper = true;
            }
        }
        //inExp.forEach(e -> ps.print(e + " "));
        for (int i = 0, sz = inExp.size(); i < sz; ++i) {
            String now = inExp.get(i);
            if (define.containsKey(now)) {
                String root = findRoot(now);
                if(!root.matches(digitPattern))root = "0";
                inExp.set(i, root);
            }
            else if(!prior.containsKey(now.charAt(0)) && !now.matches(digitPattern))inExp.set(i, "0");
        }
        //inExp.forEach(e -> ps.print(e + " "));
    }

    static Stack<Character> opers = new Stack<Character>();
    static void toPost() {
        opers.clear();
        postExp.clear();
        for (String s : inExp) {
            if (s.matches(digitPattern))
                postExp.add(s);
            else {
                if (opers.isEmpty())
                    opers.push(s.charAt(0));
                else {
                    char top = opers.peek();
                    char c = s.charAt(0);
                    if (s.equals(")")){
                        while (!opers.isEmpty() && opers.peek() != '(') {
                            postExp.add(opers.pop() + "");
                        }
                        if (!opers.isEmpty() && opers.peek() == '(')
                            opers.pop();
                    }
                    else if((c != '(' && c != '^' && prior.get(c) <= prior.get(top))){
                        for(top = opers.peek();prior.get(c) <= prior.get(top);) {
                            postExp.add(opers.pop() + "");
                            if(!opers.isEmpty())top = opers.peek();
                            else break;
                        }
                        opers.push(c);
                    }
                    else
                        opers.push(c);
                }
            }
        }
        while(!opers.isEmpty()) {
            char c = opers.pop();
            if(c == ')')continue;
            else postExp.add(c + "");
        }
        //postExp.forEach(e -> ps.print(e + " "));
    }

    static Stack<Integer> digits = new Stack<Integer>();
    static int calcResult() {
        digits.clear();
        for(String s : postExp) {
            if(s.matches(digitPattern))digits.push(Integer.parseInt(s));
            else {
                char c = s.charAt(0);
                int last1 = digits.pop(), last2 = digits.pop();
                switch (c) {
                case '-':{
                    digits.push(last2 - last1);
                    break;
                }
                case '+':{
                    digits.push(last2 + last1);
                    break;
                }
                case '*':{
                    digits.push(last2 * last1);
                    break;
                }
                case '/':{
                    digits.push(last2 / last1);
                    break;
                }
                case '%':{
                    digits.push(mod(last2, last1));
                    break;
                }
                case '^':{
                    digits.push(power(last2, last1));
                    break;
                }
                }
            }
        }
        return digits.pop();
    }

    static String[] parts;
    public static void main(String[] args) throws Exception {
//        is = new FileInputStream(fin);
//        ps = new PrintStream(new FileOutputStream(fout));
        is = System.in;
        ps = System.out;
        Scanner scanner = new Scanner(is);
        while (scanner.hasNextLine()) {
            input = scanner.nextLine().trim().toLowerCase();
            if (input.charAt(0) == 'p') {
                input = input.replaceAll(" ", "");
                input = input.substring(5);
                split();
                toPost();
                int res = calcResult();
                ps.println(res);
            }

            else {
                parts = input.split(" ");
                if (define.containsKey(parts[1]))
                    continue;
                else {
                    String root1 = findRoot(parts[1]);
                    String root2 = findRoot(parts[2]);
                    if(!root1.equals(root2))define.put(parts[1], parts[2]);
                }
            }
        }
        scanner.close();
    }
}

CFGym 100198G 题解的更多相关文章

  1. CFGym 101490J 题解

    一.题目链接 http://codeforces.com/gym/101490 二.题面 三.题意 给你n个点,代表学生所在位置,n个点,代表老师所在位置.每个学生分配一个老师.让你找出一个最小的学生 ...

  2. CFGym 101490E 题解

    一.题目链接 http://codeforces.com/gym/101490 二.题面 三.题意 给你一个图,n个点,m条边,一个x,从顶点1走到顶点n.假设从顶点1走到顶点n的最短路为d,x代表你 ...

  3. CFGym 101161I 题解

    一.题目链接 http://codeforces.com/gym/101161/problem/I 二.题意 给定一棵树,一个初始的省会城市,若干个询问,0表示修改省会城市,1表示查询去省会必须经过指 ...

  4. CFGym 101194L 题解

    一.题目链接 http://codeforces.com/gym/101194/problem/L 二.题意 有4个队伍,要打6场比赛(刚好每两个队伍都能相互比一次),若A和B比赛有3种结果: A赢B ...

  5. CFGym 101194D 题解

    一.题目链接 http://codeforces.com/gym/101194/problem/D 二.题意 给定一个数字n和一个数字k,一个n个整数的序列,让你在里面找尽可能多的长度为k的符合“要求 ...

  6. CFGym 101505I 题解

    一.题目链接 http://codeforces.com/gym/101505 二.题意 这题其实主要就是题意,理解题意后,就是水题了.我想了下,主要原因就是这几点: 1.题意太过英文化,很多句子不能 ...

  7. CFGym 100211J 题解

    一.题目 二.题意 给定一个字母表(最多也就是英文小写字母的前10个字母),一个交换表,两个字符串,判断字符串A能否通过交换表的交换方式变成字符串B. 三.思路 1.一开始,比赛时,我半模拟半记忆化地 ...

  8. [CF-GYM]Abu Tahun Mod problem题解

    前言 这道题比较简单,但我还是想了好一会 题意简述 Abu Tahun很喜欢回文. 一个数组若是回文的,那么它从前往后读和从后往前读都是一样的,比如数组\(\left\{1\right\},\left ...

  9. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

随机推荐

  1. Sublime编辑器上的Linux Vim插件常用快捷键

    Sublime编辑器上的 Vim 插件常用快捷键 vim 的设置: 在Reference-> User Settings(首选项--> 设置用户) 选项,点击进入配置文件编辑状态,默认的用 ...

  2. python 字典元素值的乘积

    my_dict = {,,} result= for key in my_dict: result=result * my_dict[key] print(result)

  3. thinkphp3.2笔记(5)创建项目 创建模型 实例化

    一 创建项目 1 拷贝框架 目录   public   thinkphp  .htaccess  index.php    [application不用拷贝,会自动生成] 2   public 下面创 ...

  4. 插件uaredirect.js实现电脑版跳转到手机版网站

    一.介绍 这段时间,有好多朋友问我,跳转到手机版的那个JS是怎么写的.其实这个JS也不是我写的,是百度siteapp下的一款跳转的产品,使用起来很方便.你可以用这款JS跳转到手机版,也可以跳转到任何你 ...

  5. Mongo Plugin插件(编辑器PyCharm的Mongo插件安装与使用)

    博主接触到MongoDB数据库.用普通的Navicat工具 是不支持的 正准备重新安装一款对应的可视化工具.刚好发现在PyCharm编辑中有连接mongoDB数据的插件 Mongo Plugin 这里 ...

  6. Oracle linux安装Oracle 11G

    Oracle  linux安装Oracle 11G 系统环境 Oracle linux   5.8.19.6(64位) Oracle     11.2.0.1(64位) 本文档详细介绍Oracle  ...

  7. App6种常见的数据加载设计

    App6种常见的数据加载设计 设计师在进行APP设计的设计时,往往会更加专注于界面长什么样,界面和界面之间怎么跳转,给予用户什么样的操作反馈,却偏偏特别容易忽略掉一个比较重要的环节,就是APP数据加载 ...

  8. SPOJ COMPANYS Two Famous Companies 最小生成树,二分,思路 难度:2

    http://www.spoj.com/problems/COMPANYS/en/ 题目要求恰好有k条0类边的最小生成树 每次给0类边的权值加或减某个值delta,直到最小生成树上恰好有k条边为0,此 ...

  9. phpstudy2017版本的nginx 支持laravel 5.X配置

    之前做开发和学习一直用phpstudy的mysql服务,确实很方便,开箱即用.QQ群交流:697028234 现在分享一下最新版本的phpstudy2017 laravel环境配置. 最新版的phps ...

  10. linux内存查看工具

    这里帮你总结了一下Linux下查看内存使用情况的多种方法~ 在做 Linux 系统优化的时候,物理内存是其中最重要的一方面.自然的,Linux 也提供了非常多的方法来监控宝贵的内存资源的使用情况.下面 ...