洛谷T32219 PS++语言

算法竞赛 算法-模拟 字符串
编辑文章

这是一道由ljq大佬出的绝世好题,虽然看似容易,实则考察了诸位OIer对于C++语言的熟悉程度。同时,该题目又以我校物竞第一大佬PS作为题目背景,充满大佬之气,值得各位前来吸收RP。而原标程又由wzx大佬亲笔书写,可以相信几乎没有疏忽之处。所以,此题也配得上黑题这一难度评分。

以下仅代表个人拙见,已AC,但不代表是最终正确程序。

我们先来梳理下编译错误有哪些情况:

  1. #define#undef后面没有空格
  2. #define后没有空格相隔的两个及以上元素(可以只有一个元素,感谢@ljq大佬的指出)
  3. #undef后有两个及以上元素
  4. #include后面不是由尖括号或引号包裹起来的一串字母
  5. 甚至不是这三个关键字
  6. 还没有#define#undef某个元素
  7. 重复#define
  8. #include的右尖括号后还有东西
  9. #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;
}

新评论

称呼不能为空
邮箱格式不合法
网站格式不合法
内容不能为空
     
    2019-01-29 10:10

    llf巨佬太强了

      Llf0703
      2019-01-29 20:14

      fAKe
      还有通过邮箱可以知道您是ljq,大家快来%

      duanyll
      2019-01-30 08:03

      %%%

    duanyll
    2019-01-29 19:38

    %LLF
    其实您可以去写P3695和P4911以及UVA12423,对您来说这种模拟题都是红题~

      Llf0703
      2019-01-29 20:11

      %dyl
      Mayan游戏和时间复杂度就已经是我的极限了。
      看来大佬平时都顺手切这三道题来娱乐,像我就只能写写红题度日。