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;	
} 
相关推荐
roman_日积跬步-终至千里1 小时前
【计算机视觉(2)】图像几何变换基础篇:从平移旋转到投影变换
人工智能·算法·计算机视觉
威哥爱编程1 小时前
【鸿蒙开发案例篇】NAPI 实现 ArkTS 与 C++ 间的复杂对象传递
c++·harmonyos·arkts
im_AMBER1 小时前
Leetcode 71 买卖股票的最佳时机 | 增量元素之间的最大差值
笔记·学习·算法·leetcode
bulingg1 小时前
聚类方法(kmeans,DBSCAN,层次聚类,GMM,EM算法)
算法·kmeans·聚类
lally.1 小时前
Kaggle Binary Classification with a Bank Dataset逻辑回归实现(准确率0.94539)
人工智能·算法·机器学习·逻辑回归
埃伊蟹黄面1 小时前
二分查找算法
c++·算法·leetcode
野蛮人6号1 小时前
力扣热题100道之78子集
算法·leetcode·职场和发展
悦来客栈的老板1 小时前
AST反混淆实战|reese84_jsvmp反编译前的优化处理
java·前端·javascript·数据库·算法
dragoooon341 小时前
[优选算法专题十一.字符串 ——NO.60~63 最长公共前缀、5最长回文子串、 二进制求和 、字符串相乘]
算法·leetcode·动态规划