本题按照我写题的全过程再写

首先看到题面,我知道要处理运算优先级的问题

所以对于宏定义中的每个运算我开一个\(map\)分别记录他的加减号,乘除号时候被括号括起来

在表达式中错误情况有三种

  1. 前面是减号或乘除号,但后面的宏定义所有的加减没有被括起来
  2. 前面是除号,但后面宏定义所有的乘除号没有被括起来
  3. 前面是加减号没有被括起来的宏定义,后面是乘除号

当我们遍历到运算符时查看上一个相邻的时表达式还是宏定义,若是宏定义检查3

当我们遍历到宏定义时查看上一个相邻的是否是运算符,若是运算符检查1,2

然后就是处理括号的问题

我们对于括号的情况进行递归判断就好,若左括号递归到下一层,若右括号回溯到上一层

在计算表达式时,只要发现错误无论在那一层直接输出结果并exit(0)

然后我发现表达式中出现了变量(是字母,但并不是宏定义)

1
#define k ( a + b )
v/k

由于我用的是\(map\),所以一旦遍历到字母我就利用\(find()\)函数判断是否是宏定义,如果是个变量就当作数字处理

然后还会有宏定义套宏定义的形式

#define sum x + y
#define mul a * sum

处理方法和表达式类似,要注意括号的形式

#define sum x + y
#define mul a * ( sum )

此时递归操作比较困难,我采用了四个变量aa,bb,cc,dd分别表示上一个操作符是什么,判断即可

所以出现了第四种错误

  1. 宏定义本身是错误的

但是会有这种情况

2
#define sum x + y
#define mul x * sum
sum + sum

本身没有调用错误的宏定义,所以对于每个宏定义,我在用一个\(map\)储存这个宏定义时候是正确的,在计算表达式的时候,顺便检查宏定义时候是正确的

然后本题还有些坑点

  1. # define s+y这类的有多余的空格所以不能从第\(8\)个位置直接开始运算,要逐一遍历
  2. n=0这种情况特判即可
#include <bits/stdc++.h>
#define PBB pair< bool , bool >
#define F first
#define S second
#define NO ("Suspicious")
#define STOP {puts(NO) , exit(0);}
using namespace std;


int n , bra , len;
string s , name , null;
map< string , PBB > def;
map< string , bool > vis;

inline int work(int star )
{
    bool mul , add , del , dive , expr ; mul = add = del = dive = expr = 0;
    for( register int i = star , t ; i < len ; i ++ )
    {
        if( s[i] == ')' ) return i;
        if( s[i] == '(' ) { i = work( i + 1 ); add = del = dive = mul = 0; continue;}
        if( s[i] == ' ' ) continue ;
        if( s[i] >= '0' && s[i] <= '9' ) { add = del = dive = mul = 0; continue; }
        if( s[i] == '+' ) { add = 1 , expr = 0; continue; }
        if( s[i] == '-' ) { del = 1 , expr = 0; continue; }
        if( s[i] == '*' )
        {
            if( expr && !def[name].F ) STOP;
            mul = 1 , expr = 0;
            continue;
        }
        if( s[i] == '/' )
        {
            if( expr && ( !def[name].F  ) ) STOP;
            dive = 1 , expr = 0;
            continue;
        }

        name = null;
        if( !expr ) name = null ;
        while( s[i] != ' ' && s[i] != '+' && s[i] != '-' && s[i] != '*' && s[i] != '/' && s[i] != ')' && s[i]!= '(' && i < len) name += s[i] , i ++ ; i--;

        if( def.find(name) == def.end() )
        {
            add = del = mul = dive = 0;

            continue;
        }
        if( !vis[name] ) STOP;
        expr = 1;
        if( del && !def[name].F ) STOP;
        if( ( mul || dive ) && !    def[name].F) STOP;
        if( dive && !def[name].S ) STOP;
        add = del = mul = dive = 0;
    }
    return 0;
}

int main()
{
    cin >> n;
    if( n == 0 ) puts("OK") , exit(0);
    getline( cin , s );
    bool add , mul , aa , bb , cc , dd , ac ;
    string cur;
    for( register int t , l ; n ; n -- )
    {
        getline( cin , s ) , len = s.size();
        l = 0;
        while( s[l] != 'd') l ++;
        l += 6;
        while( s[l] == ' ' ) l ++;
        t = l;
        while( s[t] != ' ' ) t ++;
        name = s.substr( l , t - l ) , add = 1 , mul = 1;
        aa = bb = cc = dd = 0 , ac = 1 ;
        for( t ++ ; t < len ; t ++ )
        {
            if( s[t] == '(' ) { bra ++; aa = bb = cc = dd = 0; continue; }
            if( s[t] == ')' ) { bra --; aa = bb = cc = dd = 0; continue; }
            if( s[t] == '+' ) aa = 1 , bb = cc = dd = 0;
            if( s[t] == '-' ) bb = 1 , aa = cc = dd = 0;
            if( s[t] == '*' ) cc = 1 , aa = bb = dd = 0;
            if( s[t] == '/' ) dd = 1 , aa = bb = cc = 0;
            if( !bra && ( s[t] == '+' || s[t] == '-' ) ) add = 0;
            if( !bra && ( s[t] == '*' || s[t] == '/' ) ) mul = 0;
            if( s[t] >= '0' && s[t] <= '9' ) aa = bb = cc = dd = 0;
            if( ( s[t] >= 'a' && s[t] <= 'z' ) || ( s[t] >= 'A' && s[t] <= 'Z' ) )
            {
                cur = null;
                while(s[t] != ' ' && s[t] != '+' && s[t] != '-' && s[t] != '*' && s[t] != '/' && s[t] != '(' && s[t] != ')' && t < len ) cur += s[t] , t ++;
                t -- ;
                if( def.find( cur ) != def.end() )
                {
                    if( ( bb || cc || dd ) && !def[cur].F ) ac = 0;
                    if( !vis[cur] ) ac = 0;
                    if( !bra && def[cur].F ) add = 0;
                    if( !bra && def[cur].S ) mul = 0;
                }
            }
        }
        def.insert( { name , { add , mul } } );
        vis.insert( { name , ac } );
    }

    getline( cin , s ) , len = s.size();
    work(0);
    puts("OK");
    return 0;
}
01-14 00:34