7/4(读优和写优,预处理器)
1.关于读优和写优
在c++中,普通的cin,cout,printf,scanf在遇到一些特别大的数据时,效率不高,可能导致程序运行超时。另外,在面对__int128(可以存储正负2^128大小的整数)这样无法通过常规的输入输出进行读写的数据类型,也需要我们手写读入和输出。总之,在一些情况下,进行手写读优写优能使程序更加完善
代码
点击查看代码
inline void read(int &n){//读优
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
n=x*f;
}
inline void print(int n){//写优
if(n<0){
putchar('-');
n*=-1;
}
if(n>9) print(n/10);
putchar(n % 10 + '0');
}
2.关于余数
在模运算中,有时会遇到一个负数模另一个数的情况,当然,这样会直接得到该负数本身,若要得到正确结果,将负数加n(视情况决定其大小),再进行运算
3.预处理器(2022联合省选)
题目大意:给定一个代码,要求根据其中的宏定义进行相应的宏展开并进行输出
1.既然是要求宏定义和宏展开后的结果一一对应,自然想到用map来存储字符串和字符串间的对应情况
2.注意到题目中提到了如下的情况:多次展开,递归展开。这两种情况处理起来是比较棘手的。这两种情况都是可以通过递归函数来进行处理的,在处理过程中记得用一个map记录某个字符串是否已经被展开过,以此判断是否存在递归展开的情况。在用该map递归处理时,应该回溯(因为只用关心递归树上的从根节点出发的一条路径即可)
3.在宏展开的过程中,有可能遇到展开的结果中含有空格等非法字符的情况,因此需要把这些非法字符和合法的字符串区分开来(这一点也是我觉得比较难写的。。在将合法字符串和非法字符串分开的过程中,要记录下标,还要想好substr怎么用最好,更要注意当前处理的字符串状态的转移(合法到非法,非法到合法))
4.关键是要把题目理解清楚。。在做这个题时我就看掉了题目中关于非法字符的说明,导致我认为合法字符和非法字符之间一定有空格分隔,就没有去处理第三条所提到的情况,于是就失分了。。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 100;
string s[MAXN + 5];
map<string,string> m;
map<string,bool> vis;
string c;
int n,cnt;
bool check(char a){
if(a >= '0' && a <= '9')return 1;
if(a >= 'a' && a <= 'z')return 1;
if(a >= 'A' && a <= 'Z')return 1;
if(a == '_')return 1;
return 0;
}
string out[MAXN + 5];
string change(string a){//多次展开的处理
string now[MAXN];
int pos = 0,cntt = 1,state = 0;;
for(int i = 0; i < a.size(); i++){
if(!check(a[i])){
if(state == 0){
state = -1;
pos = i;
}
else if(state == 1){
string b = a.substr(pos,i - pos);
now[cntt++] = b;
state = -1;
pos = i;
}
}
else{
if(state == 0){
state = 1;
pos = i;
}
else if(state == -1){
string b = a.substr(pos,i - pos);
now[cntt++] = b;
state = 1;
pos = i;
}
}
}
now[cntt] = a.substr(pos,a.size() - pos);
string p,ans;
for(int i = 1; i <= cntt; i++){
p = now[i];
if(m.find(now[i]) != m.end()){
if(vis.find(m[now[i]]) == vis.end() || (vis.find(m[now[i]]) != vis.end() && vis[m[now[i]]] == 0)){
vis[m[now[i]]] = 1;
p = change(m[now[i]]);
vis[m[now[i]]] = 0;//回溯一下,因为只需要关注当前搜索路径中是否存在递归展开的情况
}
}
ans += p;
}
return ans;
}
int main(){
// freopen("preprocessor.in","r",stdin);
// freopen("preprocessor.out","w",stdout);
cin >> n;
string h;
getline(cin,c);//读空行
cnt = 1;
for(int i = 1; i <= n; i++){
getline(cin,s[i]);//读入
if(s[i][0] == '#' && s[i][1] == 'd'){
for(int j = 8; j < s[i].size(); j++){
if(s[i][j] == ' '){
string a = s[i].substr(8,j - 8);
string b = s[i].substr(j + 1,s[i].size() - j - 1);
m[a] = b;
puts("");
break;
}
}
}
else if(s[i][0] == '#' && s[i][1] == 'u'){
for(int j = 7; j < s[i].size(); j++){
if(s[i][j] == ' '){
string a = s[i].substr(7,j - 7);
m.erase(a);
puts("");
break;
}
}
}
else{
int state = 0,pos;//-1表示处理非标识型字符串,1表示处理标识型字符串
cnt = 1;
for(int j = 0; j < s[i].size(); j++){
if(!check(s[i][j])){
if(state == 0){
state = -1;
pos = j;
}
else if(state == 1){
string a = s[i].substr(pos,j - pos);
out[cnt++] = a;
state = -1;
pos = j;
}
}
else{
if(state == 0){
state = 1;
pos = j;
}
else if(state == -1){
string a = s[i].substr(pos,j - pos );
out[cnt ++] = a;
state = 1;
pos = j;
}
}
}
out[cnt] = s[i].substr(pos,s[i].size() - pos);
for(int j = 1; j <= cnt; j++){
if(m.find(out[j]) != m.end()){
vis[out[j]] = 1;
cout << change(out[j]);
}
else cout << out[j];
}
puts("");
}
}
}