1 条题解
-
0
题意分析
本题聚焦于对D++程序文本的语法规则检查,核心规则涉及括号与注释。
D++程序文本由三部分构成:注释、算术表达式以及符号部分。注释能在文本各处出现,以“(”开启,“)”结束,且必须成对出现,比如“(这是一条注释)”。算术表达式以“(”起始、“)”终结,可含“=+-*/0123456789)("及注释,但不允许有空格(换行符除外),其括号需平衡,像“((1))”这类括号不平衡的就不正确。符号部分指去除注释和算术表达式后的文本,不能有“(”和“)”。
需要特别注意,除算术表达式内部,其他位置可出现空格。
输入方面,标准输入给出一段不超10000个符号的文本,内容涵盖拉丁字母、数字、括号、算术运算符号、换行符和回车符。输出则依据输入文本是否为正确的D++程序,若是输出“YES”,否则输出“NO”。如给定输入
因符合所有规则,输出“YES” 。Hello, here is a sample D++ program. It contains some arithmetical expressions like (2+2=4), (2+-/*) and ((3+3)*3=20(this is not true, but you don't have to verify it :-) )+8) ( the closing bracket in the previous comment is also in order, since this bracket does not belong to any arithmetical expression)解题思路:
1.利用
map来记录合法字符,方便后续快速判断字符是否合法。2.通过一个变量
sum来记录当前括号的匹配状态,遇到左括号(时sum加1,遇到右括号)时sum减1 。3.用
flag标记是否处于注释状态,当遇到(*时进入注释状态(flag = 1),遇到*)时退出注释状态(flag = 0) 。4.在处理过程中,根据不同的字符和状态进行相应的操作,最后根据
sum、flag和整体的合法性标记ans来判断输入的字符串是否为合法的D++程序。分析:
1.时间复杂度:对输入的每个字符都进行一次处理,假设输入字符串长度为,则时间复杂度为。因为每次字符处理的操作(如判断字符类型、更新状态变量等)基本都是常数时间操作。
2.空间复杂度:使用了一个
map来存储合法字符,map的大小是固定的(14个元素),还使用了一些辅助变量(如sum、flag、ans等),这些辅助变量的空间复杂度为常数级。所以总的空间复杂度为。实现步骤:
1.初始化数据结构和变量:初始化一个
map<char, bool>vis,将所有合法字符标记为true;初始化变量sum、flag、ans分别用于记录括号匹配状态、注释状态和整体合法性,初始值分别为0、0、1。2.字符读取与处理:通过
scanf("%c", &t)逐字符读取输入。3.当处于注释状态(
flag == 1)或者整体已经判定为不合法(ans == 0)时,仅处理结束注释的)字符,其他字符跳过,更新last字符。4.当遇到
(*时,进入注释状态(flag = 1),并将sum减1(这里减1操作可能是为了平衡后续对括号的计数逻辑)。5.当
sum为0且遇到)且前一个字符是*时,说明注释结束符号位置不对,将ans设为0表示不合法。6.根据
sum的值进行不同处理:(1)当
sum < 0时,说明括号匹配已经出错,将ans设为0并跳过后续处理。(2)当
sum > 0时,遇到)则sum减1,遇到(则sum加1,遇到非法字符(vis[t] == 0)则将ans设为0,并更新last字符。(3)当
sum == 0时,遇到(则sum加1,遇到)则sum减1,并更新last字符。7.结果输出:读取结束后,如果
sum不为0(括号未匹配)或者flag为1(注释未结束)或者ans为0(过程中发现不合法情况),则输出NO;否则输出YES。代码实现
#include<cstdio> #include<cmath> #include<cstring> #include<queue> #include<stack> #include<cstdlib> #include<iomanip> #include<string> #include<vector> #include<map> #include<string> #include<iostream> #include<algorithm> using namespace std; #define INF 0x3f3f3f3f typedef long long ll; #define Max(a,b) (a>b)?a:b #define lowbit(x) x&(-x) int main() { map<char,bool>vis; vis['1']=1; vis['2']=1; vis['3']=1; vis['4']=1; vis['5']=1; vis['6']=1; vis['7']=1; vis['8']=1; vis['9']=1; vis['0']=1; vis['+']=1; vis['-']=1; vis['*']=1; vis['/']=1; vis['\n']=1; vis['=']=1; char t,last=0; int sum=0,flag=0,ans=1; while(~scanf("%c",&t)) { if(flag==1||ans==0) { if(t==')') { if(last=='*') { flag=0; } } last=t; continue; } if(t=='*'&&last=='(') { flag=1,sum--; continue; } else if(sum==0&&t==')'&&last=='*') ans=0; if(sum<0) { ans=0; continue; } else if(sum>0) { if(t==')') { sum--; } else if(t=='(') sum++; else if(vis[t]==0) ans=0; last=t; } else { if(t=='(') { sum++; } else if(t==')') sum--; last=t; } } if(sum||flag||ans==0) puts("NO"); else puts("YES"); }代码说明:
1.头文件和命名空间:
包含了
<cstdio>用于输入输出操作,<cmath>用于数学运算(虽然本题未使用),<cstring>用于字符串处理,<queue>、<stack>用于队列和栈相关操作(本题未使用),<cstdlib>用于标准库函数,<iomanip>用于输入输出格式控制(本题未使用),<string>用于字符串操作,<vector>用于向量操作(本题未使用),<map>用于映射数据结构,<iostream>用于输入输出流,<algorithm>用于算法相关操作(本题未使用)。使用
using namespace std;使代码可以直接使用标准命名空间中的函数和类型。2.宏定义和类型定义:
#define INF 0x3f3f3f3f定义了一个很大的数,通常用于表示无穷大(本题未使用)。typedef long long ll;将long long类型重命名为ll(本题未使用)。#define Max(a,b) (a>b)?a:b定义了一个宏,用于返回两个数中的较大值(本题未使用)。#define lowbit(x) x&(-x)定义了一个宏,用于获取一个数的二进制表示中最低位的1及其后面的0(本题未使用)。3。主函数部分:
初始化
map<char, bool> vis,将所有合法字符标记为true,包括数字、算术运算符、\n和=。初始化字符变量
last为0,用于记录上一个字符;初始化sum、flag、ans变量。通过
while(~scanf("%c", &t))循环逐字符读取输入,在循环内部按照上述的实现步骤进行字符处理。循环结束后,根据
sum、flag和ans的值输出相应的结果,NO表示输入不是合法的D++程序,YES表示是合法的D++程序。
- 1
信息
- ID
- 1373
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 3
- 已通过
- 1
- 上传者