給定乙個單執行緒程式執行的記錄,包含有每個函式啟動和結束的時間。判定該份記錄是否錯誤,主要的錯誤包含:
記錄中的時間不是嚴格遞增的
乙個函式的結束時間比啟動時間更早
記錄中乙個函式有不對應的啟動操作start或結束操作end,比如出現了start卻沒有對應的end,或出現了end卻沒有出現start。而函式的start和end應該成對出現
兩個函式出現交叉的情況,而在單執行緒程式中是不會出現的,比如 a start b start a end b end
演算法分析
根據上面對可能出現錯誤的分析,我們可以分別對每一種錯誤進行處理:
記錄中的時間不是單調遞增的
對每一條記錄的時間都與前一條的時間進行比較即可判定。
乙個函式的結束時間比啟動時間更早
對出現的start和end標記的時間直接進行計算即可判定。
不對應的start和end
統計每個函式start和end的個數是否相等即可判定
兩個函式出現交叉
本題要做的是模擬乙個函式呼叫棧,其實際考察的內容是對於棧的理解和運用。
我們將函式啟動的操作視為進棧push,函式結束的操作視為出棧pop,對於乙個單執行緒的程式來說,其函式的呼叫一定滿足棧的過程。在出現函式a中呼叫函式b的情況時,函式b的結束時間一定早於函式a。這正是棧過程中先進後出原則的體現。
如果我們用棧來模擬前面的例子,則有
a start
stack a
b start
stack a b
a end
此時出現了錯誤,其操作為不在棧頂的a出棧。
對於正確的情況,比如:
a start b start b end a end
同樣用棧來模擬時有:
a start
stack a
b start
stack a b
b end
stack a
a end
stack
因此對於第三類錯誤,我們需要在程式中使用棧來模擬整個過程,即可判定是否有出現錯誤。
總結我們使用棧來模擬整個程式呼叫的過程:
首先對於每乙個記錄比較與前一條記錄的時間。
當出現了start操作的函式直接進棧。
當出現了end操作的函式時,判定該函式是否就是棧頂的函式,若不是則表明該記錄有錯誤。同時對於第二類操作中"出現了end卻沒有出現start"的情況也處理了。若出棧元素是棧頂元素時,我們在此時對其時間進行一次檢查,就可以判定第一類錯誤。
當整個過程記錄都使用棧模擬完畢後,我們還需要對當前棧內是否還有元素進行判定。若棧不為空,則出現第二類情況中"出現了start卻沒有對應的end"的情況。
此外在輸出時,題目要求按照函式呼叫樹深度優先的順序依次輸出每乙個函式。在模擬棧的過程中,函式入棧的順序也正是呼叫樹的順序,所以在處理過程中我們使用乙個序列outputlist來記錄函式入棧的順序,並在函式end操作時去更新該函式其執行時間。
其偽**如下:
for i =1.
. n if (i !=
0 and log[i]
.time < log[i -1]
.time)
return "error"
end if
if log[i]
.action ==
"start" then
stack.
push
(log[i]
) outputlist.
push
(log[i]
.funcname)
// 將該函式壓入輸出序列
else
if (stack.size ==
0 or stack.top.funcname != log[i]
.funcname)
return "error"
end if
startlog = stack.
pop(
) if startlog.time > log[i]
.time then
return "error"
end if
settime
(startlog.funcname, log[i]
.time - startlog.time)
// 記錄outputlist中名稱為startlog.funcname的函式的執行時間
end if
end for
結果分析
在實際的比賽中,該題目的通過率為14%。
在選手的程式中主要出現的錯誤有:
由於本題涉及了時間格式,在時間輸入輸出上出現問題,導致時間計算出問題
未判定函式開始時間是否大於結束時間
模擬棧結束後未檢查棧是否為空,很多選手都是因為這個原因而沒有得到100分
一開始想到了用棧模擬遞迴,但是沒想到的是開始時間居然可以等於結束時間,錯了好幾發 -_-|||
還有一句感慨:c++真是乙個物件導向的語言啊
#include
using namespace std;
#define ll long long
const
int mod =
1e9+7;
const
int maxn =
1e5+5;
const
double eps =
0.00000001
;const
int inf =
0x3f3f3f3f
;struct log
voidms(
)void
fms(
)void
print()
};mapint> mp;
string str[maxn]
;log sta[maxn]
, st[maxn]
;int top =
0, cnt =
0, c[maxn]
;bool vis = false;
intmain()
tmp.id = mp[tmp.fname];if
(op ==
"end"
)else vis = true;
}else vis = true;
}else
else vis = true;
}else}}
}if(top) vis = true;
if(vis) cout <<
"incorrect performance log\n"
;else
return0;
}
hiho學習日記 hiho一下 第五十八周
給定字串s,判定s是否存在子串s 滿足 aa abb bcc c 的形式。其中abc為連續的三個字母,且a,b,c的數量相同。原題目中數量相等的連續n n 3 個字母也是可行的,而實際上當n 3時一定包含有n 3的情況。比如 abcd 就包含有 abc 和 bcd 兩個合法子串。最基本的思路為對s的...
hiho一下 第五十八周
給定字串s,判定s是否存在子串s 滿足 aa abb bcc c 的形式。其中abc為連續的三個字母,且a,b,c的數量相同。原題目中數量相等的連續n n 3 個字母也是可行的,而實際上當n 3時一定包含有n 3的情況。比如 abcd 就包含有 abc 和 bcd 兩個合法子串。最基本的思路為對s的...
hiho一下 第二週
題目名稱 trie樹 小hi和小ho是一對好朋友,出生在資訊化社會的他們對程式設計產生了莫大的興趣,他們約定好互相幫助,在程式設計的學習道路上一同前進。這一天,他們遇到了一本詞典,於是小hi就向小ho提出了那個經典的問題 小ho,你能不能對於每乙個我給出的字串,都在這個詞典裡面找到以這個字串開頭的所...