本代码是在洛谷看过YWY_wys dalao的讲解后学着打出来的,主要是便于自己理解记忆。
- 本蒟蒻对字符、字符串的处理实在太渣了。这个博客和这个博客对string和char都介绍的不错。
- 一定要数好字符所在的位置顺序,否则……
- 每输入一组数据,先读入给出的时间复杂度,再读入并储存l个字符串,然后进行判断和处理。
- sread函数:提取字符串中的数据,一次仅读一个数(不是数字)或n,写法类似于快读。
- geto函数:提取给出的的时间复杂度。
- check函数:结果用res保存,若返回值为-1,则代表有语法错误,否则代表代复杂度。当前复杂度用now保存。需要一个栈(stack)以便最后判断语法错误。每有一个有效循环即将其变量名入栈并将ins[k]标记为1,若已被标记则表明该变量名已被用过。
- 遍历一遍代码:
如果遇到了F,首先获取变量名,用k保存,获取 F x i j 中的 i j,分别用 a b 保存。将 k 进栈。
如果 b<a ,那么没有进入循环。用一个 flag 来保存最早的没有进入循环的 k。如果都进入了,则flag始终为-1。
如果 a<=b ,代表进入循环,此时若 b-a>1000 并且 flag 为 -1 ,则本层循环对复杂度有贡献,执行 now++ 操作。同时我们用 ef[26] 保存 now++ 时 k 的信息,即ef[k]=true,并更新res。
如果遇到了E,那么同样获取变量名 k ,将k弹出栈。同时判断 flag是否等于 k ,若为 k ,代表已经出了没有贡献的循环,然后使flag=-1。再判断k是否对复杂度有贡献,若有,则当前复杂度减小,即now–,ef[k]=false;
最后return res;
再在此基础上考虑有语法错误的情况:
F 和 E 不匹配 (类似于括号匹配):
① F比E少,在函数运行到‘E’时判断栈是否为空,若为空则有语法错误,直接return -1。
② F比E多,在遍历完代码后判断栈是否不为空,若不空则有语法错误,直接return -1。
新建的变量与已经存在但未被销毁的变量重复:
用一个bool数组 ins[26] 表示当前,哪些变量被用过。那么只需在原来的基础上: 在k入栈时,判断k是否已经被用过(即k是否在栈中),若用过则有语法错误,直接return -1。
代码:
#include<bits/stdc++.h>
using namespace std;
int t,w,v,l;
string o,code[105];//code[105]是一行一行存字符串的,若要取出某个字符用code[x]
[y]
int sread(int &x,string c)//开始没搞懂&x什么意思,同桌dalao说是指针然并不能听懂。不过想起老师讲过:&取地址符可以在子函数内直接修改调用它的函数中x的值
{
int res=0;
int len=c.size();
while(c[x]<'0'||c[x]>'9'&&x<c.size())
{
if(c[x]=='n')
{
x++;
return 1000000;
}
x++;
}
while(c[x]>='0'&&c[x]<='9')
{
res=res*10+c[x]-'0';
x++;
}
return res;
}
int geto()
{
int res=0,x=3;
int len=o.size();
if(o[2]=='n') res=sread(x,o);
else res=0;
return res;
}
int check()
{
int res=0,now=0;
int a,b,x;
stack<int>s;
int flag=-1;
bool ins[26];
bool ef[26];
memset(ins,0,sizeof(ins));
memset(ef,0,sizeof(ef));
for(int i=1;i<=l;i++)
{
if(code[i][0]=='F')
{
int k=code[i][2]-'a';
if(ins[k]) return -1;
s.push(k); ins[k]=1;
x=4;
a=sread(x,code[i]);
b=sread(x,code[i]);//a与b虽然代码相同,但因为x值的改变使得两者不同,可判别先后顺序并比较二者大小从而辨别语法错误
if(b-a>1000)
{
if(flag==-1)
{
now++;
res=max(res,now);
ef[k]=1;
}
}
if(a>b)
{
if(flag==-1) flag=k;
}
}
if(code[i][0]=='E')
{
if(s.empty()) return -1;
int k=s.top();
s.pop();ins[k]=0;
if(flag==k) flag=-1;
if(ef[k])
{
ef[k]=0;
now--;
}
}
}
if(s.size()) return -1;
return res;
}
int main()
{
// freopen("in.txt","r",stdin);
scanf("%d",&t);
while(t--)
{
scanf("%d ",&l);getline(cin,o);
w=geto();
for(int i=1;i<=l;i++) getline(cin,code[i]);
v=check();
if(v==-1) printf("ERR\n");
else
{
if(w==v) printf("Yes\n");
else printf("No\n");
}
}
}