其实题目分析起来还是很清晰的
也就是判断循环中是否存在非法操作
如果存在非法操作 那么就输出ERR
否则就判断最大时间复杂度与所给是否相同
相同输出Yes
不相同就输出No
非法操作就两种
1)F和E的数量不匹配 这个很好做 在循环中F的数量一定多于E 且结束时F,E的数量相同
2)循环出现相同的变量
WA的原因:对循环的理解不够导致的 这个循环是需要状态回溯的
因为循环里面会套循环 我要求最大时间复杂度 那么我要知道循环里的循环的最大时间复杂度 即我要找到一个循环内部的最大时间复杂度 那么循环里面会有很多层循环 我要找到最大的 肯定不能依次去求 因为循环一层套一层 我并不知道循环是几层 何时结束
所以思路需要改进 即每次都去更新时间复杂度
循环里面嵌套循环 每次我都更新时间复杂度
出现F 如果循环合法且能增加时间复杂度 那么我就将cnt += 1
出现E 如果循环合法且上一次增加了时间复杂度 那么我就将cnt -= 1 这是因为相当于这个循环结束了 这样即使内层循环嵌套我也可以求出最大时间复杂度
例如:8层循环 3层里面嵌套一个3层和一个2层 那么最大时间复杂度就是6
也就是FFFFFFEEEFFEEEEE 很显然这样的做法可以维护最大时间复杂度
注意 !!! 这时候要将上一次循环的合法性弹出 要去判断上上次的循环是否增加时间复杂度
同时 需要注意 此次循环结束 那么这个循环所用的变量就可以再次使用 这也是一个需要回溯的点
每次结束我就更新最大的时间复杂度
那么该如何去回溯呢?
对于循环
维护一个栈 st 用来存储每层循环的一个性质 c 这个性质 c 有以下三种情况:
- 该层循环执行不到 即 y 大于 z,或上一层循环执行不到,那么这层循环就执行不到了 此时 c 的值记为 1。
- 该层循环可以增加时间复杂度的次数 此时 c 的值记为 2。
- 该层循环既执行得到,又不能增加时间复杂度(常数级别) 即既不满足情况 1,又不满足情况 2 此时 c 的值记为 3
对于循环使用的变量是否合法
用一个字符串 每次将使用的变量增加到该字符串末尾 当内层循环结束时 将字符串末尾删去
对于最大时间复杂度的统计
建立一个计数器 cnt,统计到该层循环时时间复杂度的幂。再建立一个量 ans,为最终时间复杂度的幂,即 cnt 可达到的最大值。
当执行到 F 且 c=2 时,cnt←cnt+1 并将 c 入栈(因为在执行 E 时需要用到 c)。
当执行到 E 且 c=2 时,cnt←cnt−1 并将栈顶元素(c)出栈
具体实现如下
#include <bits/stdc++.h>
using namespace std;
int ti[2];
int intstr(string a) {
int ansa = 100;
if (a != "n") {
ansa = 0;
for (int i = 0; i < a.size(); i++) {
ansa = ansa * 10 + a[i] - '0';
}
}
return ansa;
}
int main () {
ios::sync_with_stdio(0), cin.tie(0);
int t;cin >> t;
while (t--) {
int n;cin >> n;
string s, b, c, d, k;cin >> s;
//cnt记录一次循环的复杂度 level计算最大时间复杂度
int cnt = 0, level = 0;
//flag判断有没有语法错误
bool flag = 1;
ti[0] = 0, ti[1] = 0;
map<char, int> mp;
/*
栈顶记录上一次的状态
1)为1 说明不能进入循环
2)为2 说明可以进入循环 且可以增加时间复杂度
3)为3 说明可以进入循环 但不可以增加时间复杂度
*/
stack<int> stk;
for (int i = 1;i <= n; ++ i) {
char a;cin >> a;
if (a == 'F') {
ti[0] += 1;
cin >> b >> c >> d;
if (!flag) continue;
if (k.find(b) == string::npos) k += b;
else flag = 0;
int sc = intstr(c), sd = intstr(d);
int o = 0;
if (stk.size() && stk.top() == 1) o = 1;
if (sc > sd) o = 1;
else if (sd == 100 && o == 0 && sc != 100) o = 2;
else if (o == 0) o = 3;
stk.push(o);
if (o == 2) cnt += 1;
}
else {
ti[1] += 1;
if (!flag) continue;
if (stk.size() && stk.top() == 2) cnt --;
k = k.substr(0, k.size() - 1);
stk.pop();
}
if (ti[1] > ti[0]) flag = 0;
level = max(level, cnt);
}
//如何判断就很简单了
if (ti[0] != ti[1] || !flag) puts("ERR");
else if (s.size() == 4) {
if (level == 0) puts("Yes");
else puts("No");
}
else if (s.size() == 6) {
int tag = s[4] - '0';
if (tag == level) puts("Yes");
else puts("No");
}
else if (s.size() == 7) {
int tag = 10 * (s[4] - '0') + s[5] - '0';
if (tag == level) puts("Yes");
else puts("No");
}
}
}