这道大模拟题出的,挖的坑有点多。
分析
题目一看就是用栈来模拟,但栈元素存放什么需要分析下。
然后在纸上大概模拟下过程,分析题意,x、y有3种情况(依次判断的,即1不符合才判断2,依次类推):
1. x !=n y==n
2. y != n && (x==n || x>y)
3. x<=y (包括都为n情况和正整数)
其中只有情况1才是需要增加时间复杂度的,但是有个前提条件,在它前面的嵌套循环没有情况2,因为情况2不会执行,所以如果有情况2,其后续嵌套循环都不执行直到其结对E出栈.
所以栈中元素出栈时应该知道它是那属那种情况,所以栈元素至少要保存这个。因为要求时间复杂度,所以要知道有效情况1的最大嵌套次数,所以栈中元素也要可以表示这个,每次在有效的嵌套情况1时,更新下最大嵌套数。
情况3为O(1),可以看作O(n^0)。还有题目样例给的很良心,有个特殊情况说了,最外层循环是情况2时,时间复杂度是O(1),然后想到最外层其他两种情况,都可以正常处理。
错误有2类,但我看到题目时想到如果情况2下面嵌套循环有变量重复算错吗? 多想了,套在C语言里这也算错误的,所以。然而此处有坑ERR,Yes、No。
写代码时,觉得还有个坑,scanf读取字符时,如果前面有调用scanf,需要越过一个’\n’。
这里其实还有个可以优化,因为题目中给了最大嵌套为100,所以可以把n当作很大,如9999,这样可以统一编码。
1. y-x > 999
2. x > y
3. 其他
对中老年选手不友好…,调试比较费劲,写的过程中发现栈从1开始存比较好,栈顶含义也修改一下也比较好,不想再改了
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define MAXN 105
struct data{
int idx;//i-'a'
int cnt;//
};
int t,l,w;
bool use[MAXN], err;
int mx, top, fe, ch, x, y;
struct data st[MAXN];
char o[10];
int main()
{
freopen("complexity.in","r",stdin);
freopen("complexity.out","w",stdout);
scanf("%d",&t);
for(int i=1; i<=t; ++i){
scanf("%d%s",&l,o);
if(strcmp(o,"O(1)")==0){
w = 0;
}else{
sscanf(o,"O(n^%d)",&w);
}
if(l%2 != 0){//l为奇数、肯定不成对
err = true;
}else{
err = false;
}
mx = top = 0;
memset(use,0,sizeof(use));
for(int j=1; j<=l; ++j){
scanf("\n%c",&fe);
if(fe == 'F'){
scanf("\n%c",&ch);
if(scanf("%d",&x) == 0){
scanf("\n%c",&x);
}
if(scanf("%d",&y) == 0){
scanf("\n%c",&y);
}
//x = x=='n'?9999:x;
//y = y=='n'?9999:y;
}
if(err){//如果有变量重复 只读取不处理
continue;
}
if(fe == 'F'){
if(use[ch-'a']){
err = true;
}else{
use[ch-'a']=true;
int t = 0;
if(top)
t = st[top-1].cnt;
if((x != 'n' && y == 'n') && (t != -1)){//
st[top].cnt = ++t;
mx = max(mx, t);
}else if((y != 'n') && (x=='n'||x>y)){//
st[top].cnt = -1;//后续循环都无效直到出栈
}else{
st[top].cnt = t;
}
st[top++].idx = ch-'a';
}
}else{
if(top==0){//不成对
err=true;
}else{
use[st[--top].idx] = false;
}
}
}
if(err || top){
printf("ERR\n");
}else{
if(w == mx){
printf("Yes\n");
}else{
printf("No\n");
}
}
}
return 0;
}