省选联考 2022,记忆犹新啊。

观察数据范围发现 $1 \leq n \leq 100$,递归展开可以逐层处理。

考虑模拟展开过程,每次发现一个标识符可展开则进行递归展开,在递归之前标记当前宏为展开状态,如果发现当前展开的宏已经处于展开状态则停止继续展开。

#include<bits/stdc++.h>
using namespace std;
ifstream fin("preprocessor.in");
ofstream fout("preprocessor.out");
unordered_map<string,string> ex;
unordered_map<string,bool> on;
int n;
void add(string s){
    //#define XXXX
    //01234567
    int pos=8,lim=s.size()-1;
    string nam,cont;
    while(s[pos]!=' ') nam.push_back(s[pos]),++pos;
    for(int i=pos+1;i<=lim;i++) cont.push_back(s[i]);
    ex[nam]=cont;
}
void del(string s){
    //#undef XXXX
    //0123456
    int lim=s.size()-1;
    string nam;
    for(int i=7;i<=lim;i++) nam.push_back(s[i]);
    ex.erase(nam);
}
inline bool ischar(char x){
    return isalpha(x)||isdigit(x)||x=='_';
}
string solution(string s){
    int pos=0,lim=s.size()-1;
    string ret;
    while(pos<=lim){
        if(ischar(s[pos])){
            string x;
            while(ischar(s[pos])){
                x.push_back(s[pos]);
                ++pos;
            }
            if(ex.count(x)&&!on[x]){
                string mem=x;
                on[mem]=1;
                x=solution(ex[x]);
                on[mem]=0;
            }
            ret.append(x);
        }
        if(pos<=lim) ret.push_back(s[pos]),++pos;
    }
    return ret;
}
int main(){
    string s;
    fin>>n,getline(fin,s);
    for(int i=1;i<=n;i++){
        getline(fin,s);
        if(s[0]=='#'){
            if(s[1]=='d') add(s);
            else del(s);
            fout<<'\n';
        }
        else fout<<solution(s)<<'\n';
    }
    return 0;
}
最后修改:2024 年 11 月 25 日
如果觉得我的文章对你有用,请随意赞赏