P3952 时间复杂度

题目描述

小明正在学习一种新的编程语言 A++,刚学会循环语句的他激动地写了好多程序并 给出了他自己算出的时间复杂度,可他的编程老师实在不想一个一个检查小明的程序, 于是你的机会来啦!下面请你编写程序来判断小明对他的每个程序给出的时间复杂度是否正确。

A++语言的循环结构如下:

F i x y
    循环体
E

其中F i x y表示新建变量 ii(变量 ii 不可与未被销毁的变量重名)并初始化为 xx, 然后判断 ii 和 yy 的大小关系,若 ii 小于等于 yy 则进入循环,否则不进入。每次循环结束后 ii 都会被修改成 i +1i+1,一旦 ii 大于 yy 终止循环。

xx 和 yy 可以是正整数(xx 和 yy 的大小关系不定)或变量 nn。nn 是一个表示数据规模的变量,在时间复杂度计算中需保留该变量而不能将其视为常数,该数远大于 100100。

“E”表示循环体结束。循环体结束时,这个循环体新建的变量也被销毁。

注:本题中为了书写方便,在描述复杂度时,使用大写英文字母“O”表示通常意义下“Θ”的概念。

输入输出格式

输入格式:

 

输入文件第一行一个正整数 tt,表示有 tt(t \le 10t≤10)个程序需要计算时间复杂度。 每个程序我们只需抽取其中 F i x yE即可计算时间复杂度。注意:循环结构 允许嵌套。

接下来每个程序的第一行包含一个正整数 LL 和一个字符串,LL 代表程序行数,字符 串表示这个程序的复杂度,O(1)表示常数复杂度,O(n^w)表示复杂度为n^wnw,其 中w是一个小于100的正整数(输入中不包含引号),输入保证复杂度只有O(1)O(n^w) 两种类型。

接下来 LL 行代表程序中循环结构中的F i x y或者 E。 程序行若以F开头,表示进入一个循环,之后有空格分离的三个字符(串)i x y, 其中 ii 是一个小写字母(保证不为nn),表示新建的变量名,xx 和 yy 可能是正整数或 nn,已知若为正整数则一定小于 100。

程序行若以E开头,则表示循环体结束。

 

输出格式:

 

输出文件共 tt 行,对应输入的 tt 个程序,每行输出YesNo或者ERR(输出中不包含引号),若程序实际复杂度与输入给出的复杂度一致则输出Yes,不一致则输出No,若程序有语法错误(其中语法错误只有: ① F 和 E 不匹配 ②新建的变量与已经存在但未被销毁的变量重复两种情况),则输出ERR 。

注意:即使在程序不会执行的循环体中出现了语法错误也会编译错误,要输出 ERR

 

输入输出样例

输入样例#1: 复制

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

输出样例#1: 复制

Yes
Yes
ERR
Yes
No
Yes
Yes
ERR

说明

【输入输出样例解释1】

第一个程序 ii 从 1 到 1 是常数复杂度。

第二个程序 xx 从 1 到 nn 是 nn 的一次方的复杂度。

第三个程序有一个 F 开启循环却没有 E 结束,语法错误。

第四个程序二重循环,nn 的平方的复杂度。

第五个程序两个一重循环,nn 的一次方的复杂度。

第六个程序第一重循环正常,但第二重循环开始即终止(因为nn远大于100,100大于4)。

第七个程序第一重循环无法进入,故为常数复杂度。

第八个程序第二重循环中的变量 xx 与第一重循环中的变量重复,出现语法错误②,输出 ERR

【数据规模与约定】

对于 30\%30%的数据:不存在语法错误,数据保证小明给出的每个程序的前 L/2L/2 行一定为以 F 开头的语句,第 L/2+1L/2+1 行至第 LL 行一定为以 EE 开头的语句,L \le 10L≤10,若 xx、yy 均 为整数,xx 一定小于 yy,且只有 yy 有可能为 nn。

对于 50\%50%的数据:不存在语法错误,L \le 100L≤100,且若 xx、yy 均为整数,xx 一定小于 yy, 且只有 yy 有可能为 nn。

对于 70\%70%的数据:不存在语法错误,L \le 100L≤100。

对于 100\%100%的数据:L \le 100L≤100。


这个题我再也不想做第二遍,自己看着自己的代码都晕,绝对原创,话不说啦,上代码

#include<iostream>
#include<string>
#include<stack>
#include<string.h>
#include<vector>
#include<stdio.h>
#include<utility>
using namespace std;
bool bujin;
stack<bool>sta;
int chang;
int mi;
int max(int a, int b) {
	if (a >= b)		
		return a;
	else
		return b;
}
int main() {
	//freopen("text2.txt", "r", stdin);
	vector<char>stve;//存放变量的数组
	vector<char>ve;
	int t;
	cin >> t;
	char s[10000];
	while (t--) {
		char flagchar;
		bujin = false;
		bool bujinflag = false;
		int flag = false;
		ve.clear();
		stve.clear();
		int pre = 0;
		int lat = 0;
		int xh = 0;
		int ga, gb;
		ga = gb = 0;
		int L;
		string str;
		cin >> L >> str;
		if (str[2] == '1') {//代表复杂度为1

			ga = 1;

		}
		else {
			int i = 4;
			while (str[i] != ')') {
				gb = gb * 10 + (str[i] - '0');//b代表几次幂
				i++;
			}
		}
		getchar();
		chang = 0;
		mi = 0;
		char bian;
		bool xl = false;//当E比F多是为true
		for (int i = 1; i <= L; i++) {

			cin.getline(s, 10, '\n');//获取一行的字符串并把它们保存到s数组里
			if (xl)//说明E比F多,后面的内容就不用判断
				continue;
			if (s[0] == 'F') {
				xh++;//统计F的个数
				bian = s[2];
				for (int i = 0; i < stve.size(); i++) {//遍历数组中的变量是否与新的变量相同
					if (stve[i] == bian) {
						flag = true;
					}
				}
				stve.push_back(bian);//如果变量是新的,那么就加入到队列中
				if (!bujin) {//bujin代表由于循环
					char ch = s[4];//ch为倒数第二个字符
					if (ch >= '0'&&ch <= '9') {//说明为数字
						char last = s[strlen(s) - 1];//last为倒数第一个字符
						if (last == 'n') {
							mi = mi + 1;//mi代表n的几次幂
							sta.push(true);//sta存放的
						}
						else if (last >= '0'&&last <= '9') {//说明第二个数字也为常数
							int j = 4;
							int qian = 0;
							while (s[j] != ' ') {//计算第一个数
								qian = qian * 10 + (s[j] - '0');//qian代表i从多少开始
								j++;
							}
							int hou = 0;
							int k = j + 1;
							while (s[k] != '\0') {//计算第二个数
								hou = hou * 10 + (s[k] - '0');//hou代表i到多少结束
								k++;
							}
							if (qian > hou) {//说明前者比后者大,bujin标为true,然后以后的循环就不必进入
								bujin = true;
							}
							else {
								chang = 1;
								sta.push(false);
							}

						}
					}
					else if (ch == 'n') {//说明倒数第二个字符为n;
						char last = s[strlen(s) - 1];//last为倒数第一个字符
						if (last >= '0'&&last <= '9') {//说明为数字
							bujin = true;
							chang = 1;
							//sta.push(false);
						}
						else {
							sta.push(false);
						}
					}
				}
			}
			else if (s[0] == 'E') {

				xh--;//当为E时,就说明循环结束一个,然后xh计数减一
				if (xh < 0) {//说明E比F多,用xl标记,最后输出ERR
					xl = true;
					continue;
				}

				if (xh == 0) {
					if (!bujin)
						sta.pop();

				}
				if (xh > 0 && !bujin) {//说明内部循环结束
					pre = max(pre, chang);
					lat = max(lat, mi);//统计每一个循环后的mi的最大值
					bool biao = sta.top();
					sta.pop();
					if (biao)//当biao为true时,说明E对应的F的复杂度为1
						mi--;
				}
				char cha = stve.back();
				stve.pop_back();
				if (bujinflag) {
					if (cha == flagchar) {//说明不能进入循环的循环结束啦
						bujin = false;
						bujinflag = false;
					}
				}



			}
			if (s[0] == 'E'&&xh == 0) {//说明有成对的循环结束啦
				pre = max(pre, chang);
				lat = max(lat, mi);

				chang = 0;
				mi = 0;

			}

			if (bujin && !bujinflag) {//统计第一个不进入循环的变量
				flagchar = bian;
				bujinflag = true;
			}
		}
		if (xl)
			cout << "ERR" << endl;
		else{
			if (xh != 0 || flag) {
				cout << "ERR" << endl;
			}
			else {
				if (gb == lat && gb != 0) {
					cout << "Yes" << endl;
				}
				else {
					if (ga == pre && ga != 0) {
						cout << "Yes" << endl;
					}
					else {
						cout << "No" << endl;
					}
				}

			}
	}
			

	}

	return 0;

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值