题目大意

给出一个函数调用日志,判断日志是否合法,且求出合法日志中函数调用的时间长度。 
题目链接:performance log

题目分析

首先需要清除非法日志的几种情形: 
(1)日志的时间戳不是按照时间递增的顺序 
(2)函数A中调用函数B,而函数A先于函数B结束 
(3)函数没有被START过,却出现了END 
    每次输入一个日志记录,则判断时间戳是否递增; 
    维护一个调用堆栈call_stack,如果有函数START,则入栈,如果有函数END,则必须为call_stack顶部的函数,否则非法; 
    维护一个 哈希表 call_count表示函数调用的次数,如果函数F 进行START, 则call_count[F] + 1,若函数F进行END,则call_count[F] - 1。如果出现call_count[F] < 0,则非法; 
    在函数START时候,需要记录其开始时间 用 vector> callSeq记录。函数加入call_stack时候,需要知道该函数调用的次序,因此call_stack为 stack> 其中string为函数名,int为该函数在callSeq中的索引,用于在函数出栈时候在callSeq中找到该函数并记录其执行时间。

实现

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<stack>
#include<vector>
#include<unordered_set>
#include<unordered_map>
using namespace std; unordered_map<string, int> call_count; //记录每个函数被调用的次数,START就加1,END就减1
stack<pair<string, int>> call_stack; //调用堆栈, string函数名,int为函数的本次调用在callSeq中的索引
vector<pair<string, int> > call_seq; //最后输出的<调用函数,函数时间>
int str2intSec(char* str_time) {
int h, m, s;
sscanf(str_time, "%d:%d:%d", &h, &m, &s);
return 3600 * h + 60 * m + s;
}
string int2strSec(int sec) {
int h = sec / 3600;
int m = sec % 3600 / 60;
int s = sec % 60;
char str_time[20];
sprintf(str_time, "%02d:%02d:%02d", h, m, s);
return string(str_time);
} int main() {
int n;
char function_name[260];
char timestamp[20];
char action[20];
scanf("%d", &n);
getchar();
bool invalid = false;
int last_timestamp = -1;
for (int i = 0; i < n; i++) {
scanf("%s %s %s", function_name, timestamp, action);
if (invalid)
continue;
int sec = str2intSec(timestamp);
if (sec < last_timestamp) { //sec == last_timestap,是合法的
invalid = true;
continue;
}
last_timestamp = sec;
if (strcmp(action, "START") == 0) {
call_seq.push_back(pair<string, int>(function_name, sec));
call_stack.push(pair<string, int>(string(function_name), call_seq.size()-1));
call_count[string(function_name)] ++;
}
else if(strcmp(action, "END") == 0){
if (call_stack.empty()) {
invalid = true;
}
else{
string last_func = call_stack.top().first;
if (strcmp(function_name, last_func.c_str()) != 0) {
invalid = true;
continue;
}
call_count[last_func] --;
if (call_count[last_func] < 0) {
invalid = true;
continue;
}
int begin_index = call_stack.top().second;
int last_sec = call_seq.at(begin_index).second;
call_seq.at(begin_index).second = sec - last_sec;
call_stack.pop();
}
}
else {
invalid = true;
}
}
if (!call_stack.empty())
invalid = true;
if (invalid) {
printf("Incorrect performance log\n");
}
else {
for (int i = 0; i < call_seq.size(); i++) {
printf("%s %s\n", call_seq[i].first.c_str(), int2strSec(call_seq[i].second).c_str());
}
}
return 0;
}

hiho_1057_performance_log的更多相关文章

随机推荐

  1. Behavior Designer中的内置消息机制

    最近在用Behavior Designer,其中需要用到消息机制,看了一下其中自带了这套东西 注册 Owner.RegisterEvent<string>("Message&qu ...

  2. 通过PowerShell查看Android端log信息

    在Windows下我们可以通过在cmd中输入adb logcat相关命令来查看安卓设备上的log信息,这在PowerShell里也可以做到.所以方便做成一个脚本,以便复用.代码如下: function ...

  3. JAVA中生成Excel方法

    java 操作 Excel 最常用的就是JXL(java excel api)和POI,今先看下JXL吧.首先可以到 http://www.andykhan.com/jexcelapi/downloa ...

  4. qbxt十一系列三

    [题目分析] 这完全是个数学题啊,有些崩溃,上午考试写了两个小时,20分,于是乎 下午改啊改啊 改到10分....如果第二个圆的圆心在第一个圆.....呃 说不清楚 像下面这个图这样,两圆重叠部分中C ...

  5. Android Handler Message总结

    http://blog.csdn.net/caesardadi/article/details/8473777 当应用程序启动时,会开启一个主线程(也就是UI线程),由她来管理UI,监听用户点击,来响 ...

  6. django学习の模型

    orm:对象数据库和模型的映射.如果想以简单的方式去操作数据库,例如用类的方式去操作,就像 p = Person.get(id = 1),那么就必须使得代码和数据库的结构具有映射关系,实现这种关系,你 ...

  7. Windows 多线程知识点汇总

    一.什么叫原子性? 答:一个操作不会被分成两个时间片来执行,不会刚执行到一半,由于时间片到了,CPU就跑去执行其他线程了.在多线程环境中对一个变量进行读写时,我们需要有一种方法能够保证对一个值的操作是 ...

  8. SqlSever基础 union 将得到的横表变为纵表

    镇场诗:---大梦谁觉,水月中建博客.百千磨难,才知世事无常.---今持佛语,技术无量愿学.愿尽所学,铸一良心博客.------------------------------------------ ...

  9. sql 自增字段的控制 hibernate注解的写法

    1 创建序列,新建了一个列作为主键 create sequence pbaseinfo INCREMENT BY 1 START WITH 1 NOMAXVALUE NOCYCLE NOCACHE; ...

  10. GZFramwork快速开发框架演练之会员系统(一)框架源码下载

    GZFramwork框架开发环境为.NET 4.0 (必须)   VS2013+SQL2005+DevExpress v13.2.8+FastReport (推荐)  数据库建模工具PowerDesi ...