【题目描述】
给出了他自己算出的时间复杂度,可他的编程老师实在不想一个一个检查小明的程序,于是你的机会来啦!下面请你编写程序来判断小明对他的每个程序给出的时间复杂度是否正确。 A++A++ 语言的循环结构如下:
F i x y
循环体
E
然后判断 ii 和 yy 的大小关系,若 ii 小于等于 yy 则进入循环,否则不进入。每次循环结束后 ii 都会被修改成 i+1i+1,一旦 ii 大于 yy 终止循环。 xx 和 yy 可以是正整数(xx 和 yy 的大小关系不定)或变量 nn。nn 是一个表示数据规模的变量,在时间复杂度计算中需保留该变量而不能将其视为常数,该数远大于 100100。 EE表示循环体结束。循环体结束时,这个循环体新建的变量也被销毁。
注:本题中为了书写方便,在描述复杂度时,使用大写英文字母 OO 表示通常意义下 ΘΘ 的概念。
【输入】
第一行一个正整数 tt,表示有 t(t≤10)t(t≤10) 个程序需要计算时间复杂度。
每个程序我们只需抽取其中 FixyFixy和EE即可计算时间复杂度。注意:循环结构允许嵌套。
接下来每个程序的第一行包含一个正整数 LL 和一个字符串,LL 代表程序行数,字符串表示这个程序的复杂度,O(1)O(1)表示常数复杂度,O(nO(n^w)w) 表示复杂度为 nwnw ,其中 ww 是一个小于 100100 的正整数(输入中不包含引号),输入保证复杂度只有 O(1)O(1) 和 O(nO(n^w)w) 两种类型。
接下来 LL 行代表程序中循环结构中的 FixyFixy 或者 EE。 程序行若以 FF 开头,表示进入一个循环,之后有空格分离的三个字符(串)ixyixy,其中 ii 是一个小写字母(保证不为 nn ),表示新建的变量名,xx 和 yy 可能是正整数或 nn ,已知若为正整数则一定小于 100100。 程序行若以 EE开头,则表示循环体结束。
【输出】
输出共 tt 行,对应输入的 tt 个程序,每行输出YesYes或NoNo或者ERRERR,若程序实际复杂度与输入给出的复杂度一致则输出 YesYes,不一致则输出NoNo,若程序有语法错误(其中语法错误只有: ①FF 和 EE 不匹配 ②新建的变量与已经存在但未被销毁的变量重复两种情况),则输出ERRERR。
注意:即使在程序不会执行的循环体中出现了语法错误也会编译错误,要输出ERRERR。
【输入样例】
8
2 O(1)
F i 1 1
E
2 O(n^1)
F x 1 n
E
1 O(1)
F x 1 n
4 O(n^2)
F x 5 n
F y 10 n
E
E
4 O(n^2)
F x 9 n
E
F y 2 n
E
4 O(n^1)
F x 9 n
F y n 4
E
E
4 O(1)
F y n 4
F x 9 n
E
E
4 O(n^2)
F x 1 n
F x 1 10
E
E
【输出样例】
Yes
Yes
ERR
Yes
No
Yes
Yes
ERR
【提示】
【样例说明】
第一个程序 ii 从11 到 11 是常数复杂度。
第二个程序 xx 从 11 到 nn 是 nn 的一次方的复杂度。
第三个程序有一个 FF 开启循环却没有E结束,语法错误。
第四个程序二重循环,nn 的平方的复杂度。
第五个程序两个一重循环,nn 的一次方的复杂度。
第六个程序第一重循环正常,但第二重循环开始即终止(因为 nn 远大于 100100,100100 大于 44)。
第七个程序第一重循环无法进入,故为常数复杂度。
第八个程序第二重循环中的变量 xx 与第一重循环中的变量重复,出现语法错误②,输出 ERRERR。
【数据范围】
对于 30% 的数据:不存在语法错误,数据保证小明给出的每个程序的前 L/2L/2 行一定为以 FF 开头的语句,第 L/2+1L/2+1 行至第 LL 行一定为以 EE 开头的语句,L≤10L≤10,若 xx,yy 均为整数,xx 一定小于 yy,且只有 yy 有可能为 nn。
对于 50% 的数据:不存在语法错误,L≤100L≤100,且若 xx,yy 均为整数,xx 一定小于 yy,且只有 yy 有可能为 nn。
对于 70% 的数据:不存在语法错误,L≤100L≤100。
对于 100% 的数据:t≤10,L≤100t≤10,L≤100。
代码整体如下:
#include<cctype>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 105
#define oo 10000
using namespace std;
int sta[N], a[N];
bool can[N], used[30];
char s[10], var[N], num1[10], num2[10];
void init() {
memset(a, 0, sizeof(a));
memset(can, true, sizeof(can));
memset(used, false, sizeof(used));
}
int get1(char *a) {
int i = 4, ans = 0;
while (isdigit(a[i])) {
ans = ans * 10 + a[i] - '0';
i++;
}
return ans;
}
int get2(char *a) {
int i, l, num = 0;
if (a[0] == 'n')
return oo;
l = strlen(a);
for (i = 0; i < l; ++i)
num = num * 10 + a[i] - '0';
return num;
}
int main() {
char c;
bool flag;
int n, i, t, x, y;
int top, num, sum, maxn;
cin >> t;
while (t--) {
cin >> n >> s;
init();
num = get1(s);
flag = true;
top = 0, sum = 0, maxn = 0;
for (i = 1; i <= n; ++i) {
cin >> c;
if (c == 'F') {
cin >> var[i] >> num1 >> num2;
if (!flag) continue;
x = get2(num1);
y = get2(num2);
if (used[var[i] - 'a'])
flag = false;
sta[++top] = i;
used[var[i] - 'a'] = true;
if (x < y && y == oo) a[i] = 1, sum++;
if (x > y || !can[top - 1]) can[top] = false;
} else {
if (!flag) continue;
if (top == 0) flag = false;
used[var[sta[top]] - 'a'] = false;
if (can[top]) maxn = max(maxn, sum);
if (a[sta[top]]) sum--;
can[top] = true;
top--;
}
}
if (top != 0) flag = false;
if (!flag) cout << "ERR" << '\n';
else {
if (maxn == num) cout << "Yes" << '\n';
else cout << "No" << '\n';
}
}
return 0;
}