給定字串s,判定s是否存在子串s』滿足」aa…abb…bcc…c」的形式。其中abc為連續的三個字母,且a,b,c的數量相同。
原題目中數量相等的連續n(n>3)個字母也是可行的,而實際上當n>3時一定包含有n=3的情況。比如」abcd」就包含有」abc」和」bcd」兩個合法子串。
最基本的思路為對s的每乙個子串進行判定是否滿足要求。列舉子串的起點、終點以及檢查是否合法。
假設s的長度為n,則時間複雜度為o(n^3)。
for i = 0..n-1
for j = 0..n-1
check(s[i..j])
endforend
for
這樣的做法對於n稍大的資料來說就會超過時限。
進一步考慮,由於合法子串中相同的字母總是連續的,我們不妨用(c,n)來表示一串連續相同的字母,比如」aaa」表示(a,3),」bb」表示為(b,2)。
我們將整個字串s用(c,n)表示,得到的序列。其中我們合法的子串也可以表示為。
則演算法改變為在序列中判定是否存在連續的3個元素滿足c[i],c[i+1],c[i+2]連續且n[i] == n[i+1] == n[i+2]。
預處理時間為o(n),得到的序列長度最大為n,所以整體的時間複雜度降低為o(n)。
for i = 1 .. t-2
if (c[i]+1 == c[i+1] and c[i+1]+1 == c[i+2]) and (n[i] == n[i+1] == n[i+2])
return
true
endif
endfor
然而實際執行會發現,這個演算法是不正確的。比如:」aaaabbccc」,其對應的序列為,根據我們上面的演算法並不能找到合法子串。但實際上存在合法子串」aabbcc」。
很顯然,問題出在我們對於n[i],n[i+1],n[i+2]的判定上。通過上面的反例我們可以發現,在子串中n[i],n[i+2]的值其實是可以變動的,唯一固定的是n[i+1]的值。當n[i]>n[i+1]時,我們只要刪去前面的若干個字母,就能夠使得n[i]==n[i+1]。同理對於n[i+2]>n[i+1]時,我們刪去後面的字母。因此只要有n[i]>=n[i+1],n[i+2]>=n[i+1],就一定能夠通過變換使得n[i] == n[i+1] == n[i+2]。
改正後我們的演算法**為:
for i = 1 .. t-2
if (c[i]+1 == c[i+1] and c[i+1]+1 == c[i+2]) and (n[i] >= n[i+1] and n[i+1] <= n[i+2])
return
true
endif
endfor
在實際的比賽中,該題目的通過率僅為26%。
但根據賽後的統計結果,大部分的選手都使用了樸素的演算法通過了規模較小的資料點。在該題目上獲取了10~60不等的分數。
其中比較有意思的是有一位選手僅僅判定連續3個字母是否連續,也獲得了60的分數。
而分布在70~90分數段的程式,隨機抽取了若干樣本,發現大多數都是想到了正確演算法的。而導致他們丟分的主要原因則是多組資料產生的初始化問題。
#include
int main() ;
bool flag = false;
for (int i = 1; i <= len; i++) else
pre = cur;
}flag ? puts("yes") : puts("no");
}return
0;}
hiho學習日記 hiho一下 第五十八周
給定字串s,判定s是否存在子串s 滿足 aa abb bcc c 的形式。其中abc為連續的三個字母,且a,b,c的數量相同。原題目中數量相等的連續n n 3 個字母也是可行的,而實際上當n 3時一定包含有n 3的情況。比如 abcd 就包含有 abc 和 bcd 兩個合法子串。最基本的思路為對s的...
hihor日記 hiho一下 第五十九周
給定乙個單執行緒程式執行的記錄,包含有每個函式啟動和結束的時間。判定該份記錄是否錯誤,主要的錯誤包含 記錄中的時間不是嚴格遞增的 乙個函式的結束時間比啟動時間更早 記錄中乙個函式有不對應的啟動操作start或結束操作end,比如出現了start卻沒有對應的end,或出現了end卻沒有出現start。...
hiho一下 第五十四周 (縮點 dfs
這道題錯了好幾次,沒有看到一定從1號開始走。題目的意思就是問你從一號開始走,最多可以吃多少草。直接用到有向圖的雙連通的trajan演算法給圖縮點,再重新新建乙個縮完點之後的圖,然後直接從1號開始dfs就可以了。include include include includeusing namespac...