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
- 上传者