CCF-CSP 37-3 模板展开(templating)【C++】

题目

题目链接

TUOJhttps://sim.csp.thusaac.com/contest/37/problem/2参考:第37次CCF CSP第三题 模板展开 题解_模板展开csp-CSDN博客

思路

一、核心设计思想

系统将变量分为两种存储方式:

  1. 直接赋值:立即计算表达式结果并存储

  2. 间接赋值:存储表达式结构和依赖关系,查询时动态计算

二、变量存储结构

每个变量包含两个部分:

  • 固定值部分:所有直接字符串的长度总和

  • 依赖列表:引用的其他变量ID

这种设计允许表达式既包含字符串字面量,也包含对其他变量的引用。

三、三种操作详解

1. 操作1:直接赋值

处理流程

  • 立即计算所有部分的总和

  • 字符串字面量直接累加长度

  • 变量引用($开头)递归计算其当前值并累加

  • 将最终结果存入变量的固定值部分,清空依赖列表

特点:赋值时完成所有计算,后续查询直接返回值

2. 操作2:间接赋值

处理流程

  • 分离字符串和变量引用

  • 字符串字面量累加到固定值部分

  • 变量引用记录到依赖列表中

  • 不进行实际计算

特点:建立依赖关系网,查询时才计算

3. 操作3:查询变量值

处理流程

  • 检查缓存(len数组)

  • 若未缓存:固定值 + 递归计算所有依赖变量的值

  • 缓存结果后返回

四、计算与缓存机制

递归计算:

  • 对于间接赋值的变量,需要递归计算其依赖的所有变量

  • 自动处理多层嵌套的变量引用

缓存优化:

  • len数组缓存每个变量的计算结果

  • 每次操作开始时清空缓存(简单但低效)

  • 避免重复计算相同变量

代码

【对上面的代码按照自己的习惯进行了改写,但是逻辑基本一致】

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define debug(a) cout<<"debug:"<<a<<endl;
const int N=2e3+5;
const int MOD=1e9+7;
int cnt=0; 

struct var{
//	int kind; //1:直接 2:间接 没用 
	ll l; //可能会爆int 
	vector<int>r; //依赖 
};

vector<var>v(N);
int len[N];
unordered_map<string,int>mp;

int get_idx(string s)
{
//	if(mp[s]!=NULL) ; //warn:不能mp[s]!=NULl来判断;写出mp[s]就会自动创建并赋值为0 
	if(mp.count(s)==0) mp[s]=cnt++; //这么判断才对 
	return mp[s];
}

int get_value(int idx) //传入下标 
{
	if(len[idx]!=-1) return len[idx];
	ll ans=v[idx].l;//int可能会爆 
	for(auto k:v[idx].r) 
	{
		//warn不能只加基础值,可能该变量间接引用的其他变量也是间接赋值,所以要递归计算 
		//ans=(ans+v[k].l)%MOD; 
		ans=(ans+get_value(k))%MOD; 
	}
	return ans;
}

void solve()
{
	int n; cin>>n;
	cin.get();
	while(n--)
	{
		memset(len,-1,sizeof(len)); //warn:应该是-1代表未计算 
		string line,s1;
		getline(cin,line); 
		stringstream ss(line);
		int op;
		ss>>op>>s1;
		int idx=get_idx(s1);
		if(op==1) //直接赋值 
		{
			v[idx].r.clear();
//			v[idx].l=0; //WARN:可以把自己直接赋值给自己 
			string now;
			ll res=0; //WARN:局部变量初始化 
			while (ss>>now)
			{
				if(now[0]=='$')
				{
					now.erase(0,1); //删$ 
					res=(res+get_value(get_idx(now)))%MOD;
				}
				else res=(res+now.size())%MOD; //WARN:不带$的是字面量不是变量 
			}
			v[idx].l=res;
		}
		else if(op==2) //间接赋值 
		{
			v[idx].r.clear();
			v[idx].l=0; //不会自己依赖自己,否则成环 
			
			ll res=0;
			string now;
			while (ss>>now)
			{
				if(now[0]=='$')
				{
					now.erase(0,1); //删$ 
					v[idx].r.push_back(get_idx(now));
				}
				else res=(res+now.size())%MOD;
			}
			v[idx].l=res;
		}		
		else if(op==3) cout<<get_value(idx)<<endl;
	}
}

int main()
{
	ios::sync_with_stdio(0),cin.tie(0);
	solve();
	return 0;	
} 
相关推荐
We་ct13 小时前
LeetCode 228. 汇总区间:解题思路+代码详解
前端·算法·leetcode·typescript
charlee4413 小时前
为什么现代 C++ 库都用 PIMPL?一场关于封装、依赖与安全的演进
c++·智能指针·raii·pimpl·编译防火墙·封装设计
AIpanda88813 小时前
如何借助AI销冠系统提升数字员工在销售中的成效?
算法
啊阿狸不会拉杆13 小时前
《机器学习导论》第 7 章-聚类
数据结构·人工智能·python·算法·机器学习·数据挖掘·聚类
木非哲13 小时前
机器学习--从“三个臭皮匠”到 XGBoost:揭秘 Boosting 算法的“填坑”艺术
算法·机器学习·boosting
MSTcheng.13 小时前
CANN ops-math算子的跨平台适配与硬件抽象层设计
c++·mfc
code monkey.13 小时前
【Linux之旅】Linux 进程间通信(IPC)全解析:从管道到共享内存,吃透进程协作核心
linux·c++·ipc
薛定谔的猫喵喵13 小时前
基于C++ Qt的唐代诗歌查询系统设计与实现
c++·qt·sqlite
小辉同志13 小时前
437. 路径总和 III
算法·深度优先·广度优先
阿昭L13 小时前
C++异常处理机制反汇编(三):32位下的异常结构分析
c++·windows·逆向工程