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');
}
  可以看出,读优写优是根据getchar和putchar等函数的高效来设计的。在遇到要求我们输出较多数据时,可以采用此方法。

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("");
		}
		
	}
}
posted @ 2022-07-04 21:40  腾云今天首飞了吗  阅读(423)  评论(0编辑  收藏  举报