本题按照我写题的全过程再写
首先看到题面,我知道要处理运算优先级的问题
所以对于宏定义中的每个运算我开一个\(map\)分别记录他的加减号,乘除号时候被括号括起来
在表达式中错误情况有三种
- 前面是减号或乘除号,但后面的宏定义所有的加减没有被括起来
- 前面是除号,但后面宏定义所有的乘除号没有被括起来
- 前面是加减号没有被括起来的宏定义,后面是乘除号
当我们遍历到运算符时查看上一个相邻的时表达式还是宏定义,若是宏定义检查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
分别表示上一个操作符是什么,判断即可
所以出现了第四种错误
- 宏定义本身是错误的
但是会有这种情况
2
#define sum x + y
#define mul x * sum
sum + sum
本身没有调用错误的宏定义,所以对于每个宏定义,我在用一个\(map\)储存这个宏定义时候是正确的,在计算表达式的时候,顺便检查宏定义时候是正确的
然后本题还有些坑点
# define s+y
这类的有多余的空格所以不能从第\(8\)个位置直接开始运算,要逐一遍历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;
}