这是一道由ljq大佬出的绝世好题,虽然看似容易,实则考察了诸位OIer对于C++语言的熟悉程度。同时,该题目又以我校物竞第一大佬PS作为题目背景,充满大佬之气,值得各位前来吸收RP。而原标程又由wzx大佬亲笔书写,可以相信几乎没有疏忽之处。所以,此题也配得上黑题这一难度评分。
以下仅代表个人拙见,已AC,但不代表是最终正确程序。
我们先来梳理下编译错误有哪些情况:
#define
和#undef
后面没有空格(可以只有一个元素,感谢@ljq大佬的指出)#define
后没有空格相隔的两个及以上元素#undef
后有两个及以上元素#include
后面不是由尖括号或引号包裹起来的一串字母- 甚至不是这三个关键字
- 还没有
#define
就#undef
某个元素 - 重复
#define
#include
的右尖括号后还有东西#include
尖括号或引号中元素为空
需要注意的是空格无论留多少都不会影响编译,#include
后面可以不留空格(像我自己打代码就从来不留)。
上面的东西前五个直接用字符串基础知识判断即可,对于第6个,我们可以使用map
去重,当#undef
的时候判断一下是否存在,如果不存在则给出ce,否则把这个元素删除即可。
剩下的就是统计答案了,注意头文件可能会有重复的情况,这时我们再开一个map
去下重就行了。
然后是我的清(巨)晰(长)易(无)懂(比)的代码,各位将就看看吧,欢迎hack:
// ©2019 Llf0703
// It's the std code of https://www.luogu.org/problemnew/show/T32219
// visit https://llf0703.com/p/luogu-t32219.html to hack me in the comment
#include<bits/stdc++.h>
using namespace std;
map <string,int> mp,mp2;
int main()
{
string s;
int n,ans=0;
scanf("%d",&n);
bool ce=0;
getline(cin,s);
for (int i=1;i<=n;i++)
{
getline(cin,s);
int len=s.length();
string x=s.substr(0,8),y=s.substr(0,8),z=s.substr(0,7); //include ' '
if (x!="#include" && y!="#define " && z!="#undef ")
{
ce=1;
break;
}
if (x=="#include")
{
int j=8;
while (s[j]==' ' && j<len) j++;
if ((s[j]!='\"' && s[j]!='<') || j==len)
{
ce=1;
break;
}
int stat=j+1;
char goal;
if (s[j]=='\"') goal='\"';
else goal='>';
j++;
while (s[j]!=goal && j<len) j++;
if (j==len)
{
ce=1;
break;
}
int ed=j-1;
if (ed-stat+1==0)
{
ce=1;
break;
}
j++;
while (s[j]==' ' && j<len) j++;
if (j!=len)
{
ce=1;
break;
}
string name=s.substr(stat,ed-stat+1);
if (mp.find(name)==mp.end()) ans++;
mp[name]=1;
}
else if (y=="#define ")
{
int j=8;
while (s[j]==' ' && j<len) j++;
if (j==len)
{
ce=1;
break;
}
int stat=j;
while (s[j]!=' ' && j<len) j++;
int ed=j-1;
string name=s.substr(stat,ed-stat+1);
if (mp2.find(name)!=mp2.end())
{
ce=1;
break;
}
mp2[name]=1;
}
else if (z=="#undef ")
{
int j=7;
while (s[j]==' ' && j<len) j++;
if (j==len)
{
ce=1;
break;
}
int stat=j;
while (s[j]!=' ' && j<len) j++;
int ed=j-1;
while (s[j]==' ' && j<len) j++;
if (j!=len)
{
ce=1;
break;
}
string name=s.substr(stat,ed-stat+1);
if (mp2.find(name)==mp2.end())
{
ce=1;
break;
}
mp2.erase(name);
}
}
if (ce) printf("Compile Error");
else printf("%d",ans);
return 0;
}
llf巨佬太强了
fAKe
还有通过邮箱可以知道您是ljq,大家快来%
%%%
%LLF
其实您可以去写P3695和P4911以及UVA12423,对您来说这种模拟题都是红题~
%dyl
Mayan游戏和时间复杂度就已经是我的极限了。
看来大佬平时都顺手切这三道题来娱乐,像我就只能写写红题度日。