hiho學習日記 hiho一下 第五十八周

2021-09-05 09:36:28 字數 2383 閱讀 8247

給定字串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-

1check

(s[i.

.j])

end for

end 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

end if

end for

然而實際執行會發現,這個演算法是不正確的。比如:「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

end if

end for

在實際的比賽中,該題目的通過率僅為26%。

但根據賽後的統計結果,大部分的選手都使用了樸素的演算法通過了規模較小的資料點。在該題目上獲取了10~60不等的分數。

其中比較有意思的是有一位選手僅僅判定連續3個字母是否連續,也獲得了60的分數。

而分布在70~90分數段的程式,隨機抽取了若干樣本,發現大多數都是想到了正確演算法的。而導致他們丟分的主要原因則是多組資料產生的初始化問題。

#include

using namespace std;

#define ll long long

const

int mod =

1e9+7;

const

int maxn =

1e7+5;

const

double eps =

0.00000001

;const

int inf =

0x3f3f3f3f

;int c[maxn]

, m[maxn]

;bool solve()

m[cnt]++;

}for

(ll i =

1; i <= cnt -

1; i ++)if

(c[i -1]

+1== c[i]

&& c[i]+1

== c[i +1]

&& m[i -1]

>= m[i]

&& m[i]

<= m[i +1]

)return true;

return false;

}int

main()

return0;

}

hiho一下第143周

題目1 hiho密碼 時間限制 10000ms 單點時限 1000ms 記憶體限制 256mb 描述 小ho根據最近在密碼學課上學習到的知識,開發出了一款hiho密碼,這款密碼的秘鑰是這樣生成的 對於一種有n個字母的語言,選擇乙個長度為m的單詞 將組成這個單詞的所有字母按照順序不重複的寫出 即遇到相...

hiho 學習日記 hiho一下第二十八周 (堆)

堆的形狀是乙個完全二叉樹,對於最大堆任意根的權值大於左右孩子的權值,而最小堆的任意根的權值小於左右孩子的權值 這裡演示的是最大堆 當插入乙個值的時候,把這個值新增到堆尾中,然後向上調整 voidup int p heap p a void insert int a 刪除堆頂的值的時候,把堆尾的元素賦...

hiho一下 第197周 逆序單詞

時間限制 10000ms 單點時限 1000ms 記憶體限制 256mb 在英文中有很多逆序的單詞,比如dog和god,evil和live等等。現在給出乙份包含n個單詞的單詞表,其中每個單詞只出現一次,請你找出其中有多少對逆序單詞。第1行 1個整數,n,表示單詞數量。2 n 50,000。第2.n ...