原题链接CF7E Defining Macros
这个黑题感觉好像不是很黑
1.理解题意
输入 n 个 #define 语句,然后给一个表达式,让你判断该表达式是不是 ‘Suspicious’ 的。 ‘Suspicious’ 的定义是某一个 #define 定义的东西被拆开来了。
如:
1 2 3
| #define haha ha+ha #define p haha-haha p
|
这是 ‘Suspicious’ 的,因为第二个haha被拆开了。本来是:
1 2 3
| (ha+ha)-(ha+ha) = ha+ha - ha-ha
|
现在是:
2.思路
对于一个表达式,在括号外面的最低级的运算符就是该表达式的优先级。比如说 (x+y)∗z/p 的优先级就是 $ * $ 或者 $ / $ 。
我们把全在运算符括号里面(或者没有运算符)的表达式记为 0 级, + 或者 − 为 1 级, ∗ 或 / 为 2 级。
不难发现, 0 级的表达式是不可能被拆分的。
1 级的表达式的前面有 ∗ 或 / 或 − 会被干掉 或者 后面有 ∗ 或 / 会被干掉。
2 级的表达式的前面有 / 才会被干掉。
注意:这里的“有”指直接相邻。
所以我们可以先 预处理出所有表达式的优先级 ,然后我们惊奇地发现,所有表达式之间的调用关系为 一张有向无环图!
所以我们可以从调用方到被调用方都连上边,然后愉快地DFS 。
然后就好了。
3.全解代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
| #include<cstdio> #include<string> #include<map> #include<vector> using namespace std; const int N=110; inline bool isCH(char ch){ return ch>='A'&&ch<='Z'||ch>='a'&&ch<='z'; } inline int read() { int num=0;char ch=getchar(); while (ch>'9'||ch<'0') ch=getchar(); while (ch<='9'&&ch>='0') num=(num<<1)+(num<<3)+(ch^48),ch=getchar(); return num; } inline void getdef() { char ch=getchar(); while (ch!='#') ch=getchar(); while (ch!='d') ch=getchar(); while (ch>='a'&&ch<='z') ch=getchar(); return; } inline string getS() { char ch=getchar();string s=""; while (ch==' ') ch=getchar(); while (ch!=' ') s+=ch,ch=getchar(); return s; } inline string getL() { char ch=getchar();string s=""; while (ch!='\n'&&ch!=EOF) { if (ch!=' ') s+=ch; ch=getchar(); } return s; } inline void put(string s){ for(int i=0;i<s.length();++i)putchar(s[i]);puts(""); }
int n; string op; string A[N],B[N]; map<string,int> mp; int C[N]; vector<int> G[N]; vector<char> L[N],R[N]; bool vis[N]; bool safe[N]; inline void Dfs(int cur) { for (int i=0;i<G[cur].size();++i) { int to=G[cur][i];char le=L[cur][i],ri=R[cur][i]; if (!vis[to]) { vis[to]=1; Dfs(to); } if (C[to]==1) if (le=='*'||le=='/'||le=='-'||ri=='*'||ri=='/') safe[cur]=0; else if (C[to]==2) if (le=='/') safe[cur]=0; safe[cur]&=safe[to]; } return; } int main() { n=read(); for (int i=1;i<=n;++i) { getdef(); A[i]=getS(); B[i]=getL(); mp[A[i]]=i; int inb=0; for (int j=0;j<B[i].length();++j) { if (B[i][j]=='(') ++inb; else if (B[i][j]==')') --inb; else if (inb==0) { if (B[i][j]=='+'||B[i][j]=='-') C[i]=1; else if (!C[i]&&(B[i][j]=='*'||B[i][j]=='/')) C[i]=2; } } } for (int i=1;i<=n;++i) { for (int j=0;j<B[i].length();++j) { if (!isCH(B[i][j])) continue; string s="";int now=0; int k=j; while (k<B[i].length()&&isCH(B[i][k])) s+=B[i][k],++k; if (mp[s]) { L[i].push_back(j?B[i][j-1]:'#'); R[i].push_back(k<B[i].length()?B[i][k]:'#'); G[i].push_back(mp[s]); } j=k; } safe[i]=1; } for (int i=1;i<=n;++i) if (!vis[i]) vis[i]=1,Dfs(i); op=getL(); for (int j=0;j<op.length();++j) { if (!isCH(op[j])) continue; string s="";int now=0; int k=j; while (k<op.length()&&isCH(op[k])) s+=op[k],++k; if (mp[s]) { if (!safe[mp[s]]) { puts("Suspicious"); return 0; } else if (C[mp[s]]==2&&j&&op[j-1]=='/') { puts("Suspicious"); return 0; } else if (C[mp[s]]==1 &&(j&&(op[j-1]=='/'||op[j-1]=='*'||op[j-1]=='-') ||k<op.length()&&(op[k]=='/'||op[k]=='*'))) { puts("Suspicious"); return 0; } } j=k; } puts("OK"); return 0; }
|