Codeforces Beta Round #7 E. Defining Macros(二叉表达式树)

来源:互联网 发布:阿里云ecs无法发邮件 编辑:程序博客网 时间:2024/05/22 14:54

Most C/C++ programmers know about excellent opportunities that preprocessor #define directives give; but many know as well about the problems that can arise because of their careless use.

In this problem we consider the following model of #define constructions (also called macros). Each macro has its name and value. The generic syntax for declaring a macro is the following:

#define macro_name macro_value

After the macro has been declared, "macro_name" is replaced with "macro_value" each time it is met in the program (only the whole tokens can be replaced; i.e. "macro_name" is replaced only when it is surrounded by spaces or other non-alphabetic symbol). A "macro_value" within our model can only be an arithmetic expression consisting of variables, four arithmetic operations, brackets, and also the names of previously declared macros (in this case replacement is performed sequentially). The process of replacing macros with their values is called substitution.

One of the main problems arising while using macros — the situation when as a result of substitution we get an arithmetic expression with the changed order of calculation because of different priorities of the operations.

Let's consider the following example. Say, we declared such a #define construction:

#define sum x + y

and further in the program the expression "2 * sum" is calculated. After macro substitution is performed we get "2 * x + y", instead of intuitively expected "2 * (x + y)".

Let's call the situation "suspicious", if after the macro substitution the order of calculation changes, falling outside the bounds of some macro. Thus, your task is to find out by the given set of #define definitions and the given expression if this expression is suspicious or not.

Let's speak more formally. We should perform an ordinary macros substitution in the given expression. Moreover, we should perform a "safe" macros substitution in the expression, putting in brackets each macro value; after this, guided by arithmetic rules of brackets expansion, we can omit some of the brackets. If there exist a way to get an expression, absolutely coinciding with the expression that is the result of an ordinary substitution (character-by-character, but ignoring spaces), then this expression and the macros system are called correct, otherwise — suspicious.

Note that we consider the "/" operation as the usual mathematical division, not the integer division like in C/C++. That's why, for example, in the expression "a*(b/c)" we can omit brackets to get the expression "a*b/c".


题意:给一堆定义好的宏,然后给你一个表达式,问这个表达式是否安全,如: #define a x+y,那么表达式2*a就是不安全的,因为会被替换成2*x+y.


分析:不合法的情况有那么几种:加号连接的两个式子中优先级最低的运算符为加减号,减号连接的后一个式子中优先级最低的运算符为加减号,除号连接的两个式子中右式子不是一个整体或左式子由加减号连接。那么我们可以通过建立二叉表达式树来获取每个宏的优先级最低运算符,根据表达式记忆化建立表达式树,这道题没必要真的把树给建出来,只需要保留每次合并后剩下根节点的安全级别就行,另外此题数据巨坑无比,#(空格)define 和 n = 0这种数据都有。


#include<iostream>#include<string>#include<cstdlib>#include<cstdio>#include<set>#include<map>#include<vector>#include<cstring>#include<stack>#include<cmath>#include<queue>#define INF 0x3f3f3f3f#define N 210using namespace std;int n;map <string,int> f,f2;const bool camp[7][7] ={{1,1,0,0,0,1,1},{1,1,0,0,0,1,1},{1,1,1,1,0,1,1},{1,1,1,1,0,1,1},{0,0,0,0,0,0,0},{0,0,0,0,0,0,0},{0,0,0,0,0,0,0}};char st[N],str[101][N];int idx(char c){switch(c){case '+' : return 0;case '-' : return 1;case '*' : return 2;case '/' : return 3;case '(' : return 4;case ')' : return 5;case '\0' : return 6;}}void GG(){    printf("Suspicious\n");    exit(0);}void oper(stack<char> &s1,stack<int> &s2){int a = s2.top();s2.pop();int b = s2.top();s2.pop();char op = s1.top();s1.pop();switch (op){case '+' : s2.push(2);break;case '-' : if(a == 2) GG();s2.push(2);break;case '*' : if(a == 2 || b == 2) GG();s2.push(3);break;case '/' : if(a != 1 || b == 2) GG();s2.push(3);break;}}int Build(char st[]){    stack <char> s1;    stack <int> s2;int pos = 0;while(st[pos] != '\0'){if((st[pos] >= 'a' && st[pos] <= 'z') || (st[pos] >= '0' && st[pos] <= '9') || (st[pos] >= 'A' && st[pos] <= 'Z')){            string now = "";            while((st[pos] >= 'a' && st[pos] <= 'z') || (st[pos] >= '0' && st[pos] <= '9') || (st[pos] >= 'A' && st[pos] <= 'Z'))            {                now = now + st[pos];                 pos++;            }            pos--;            if(!f2[now])            {                if(f[now]) f2[now] = Build(str[f[now]]);                else f2[now] = 1;            }            s2.push(f2[now]);while(s1.size() && camp[idx(s1.top())][idx(st[pos+1])]) oper(s1,s2);}else{    s1.push(st[pos]);if(s1.top() == ')'){                s1.pop();                s1.pop();                s2.pop();                s2.push(1);                while(s1.size() && camp[idx(s1.top())][idx(st[pos+1])]) oper(s1,s2);}}pos++;}return s2.top();}int main(){    scanf("%d",&n);    if(n == 0)    {        printf("OK\n");        return 0;    }    for(int i = 1;i <= n;i++)    {        string tem;char temp[200];        while(cin>>tem && tem != "define\0" && tem != "#define\0");        scanf("%s",temp);        tem = temp;        f[tem] = i;        cin.getline(str[i],201);    }    for(int i = 1;i <= n;i++)    {        int k = 0,len = strlen(str[i]);        for(int j = 0;j <= len;j++)         if(str[i][j] != ' ') str[i][k++] = str[i][j];    }    cin.getline(st,201);    int k = 0,len = strlen(st);    for(int j = 0;j <= len;j++)     if(st[j] != ' ') st[k++] = st[j];Build(st);printf("OK\n");}


0 0
原创粉丝点击