計蒜客 2019計蒜之道D

2021-09-25 01:47:39 字數 1953 閱讀 8489

題意:

​ 現在給定你乙個字串 s

ss 以及乙個整數 k

kk,請求出 s

ss的字典序最小的長度為 k

kk的子串行。

資料範圍:0

∣s∣≤

5000000

00∣s∣≤

5000

000

樣例輸入:

helloworld

5

樣例輸出:

ellld
思路:

假如我們先不考慮長度為k的限制我們應當怎麼做?

​ 我們以樣例為例子。從左到右掃瞄字串一遍:h、然後e,因為e的字典序比h小所以h不應該在e前面,所以把h刪去,此時待選序列只有e;然後掃瞄l、l、o、r,此時待選序列中有ellor;然後掃瞄l,因為r比l大,所以r不應該在l之前,把r刪除,同樣o也是如此,現在待選序列就只剩elll;然後掃瞄d。按照前面的原理,所以elll都刪去,現在待選序列中只有d。

不過前面的部分是否有些似曾相識,這不是符合單調棧的性質嗎。所以前面的問題我們可以用單調棧來解決。

那麼現在有了長度為k的限制,我們應該怎麼做?

首先我們發現,假如字串長度為n,那麼想要答案最優就要從第1~(n-k+1)中取乙個最小的字母。這個就相當於從單調棧中取棧底的元素,並刪去(這個位置以及這個位置之前的都不能用了,但因為這個位置之前的在單調棧中不存在,故只刪除這乙個即可)。接下來取第二個字元,那麼就是將第(n-k+2)加入單調棧,然後從單調棧中棧底元素並從單調棧刪去。從單調棧中取棧底元素其實就是單調佇列。

**:

#include

#define mset(a,b) memset(a,b,sizeof(a))

using

namespace std;

typedef

long

long ll;

const

int inf=

0x3f3f3f3f

;char s[

5000000+10

],st[

5000000+10

],ans[

5000000+10

];intmain()

int cnt=0;

ans[cnt++

]=st[p++];

//取出棧底字元作為答案的第乙個字元。

for(

int i=w+

1;i<=ls;

++i)

ans[cnt]

='\0'

;printf

("%s\n"

,ans)

;return0;

}

單調佇列用deque實現:

#include

#define mset(a,b) memset(a,b,sizeof(a))

using

namespace std;

typedef

long

long ll;

const

int inf=

0x3f3f3f3f

;string s,ans;

deque<

char

> st;

intmain()

ans+

=st.

front()

; st.

pop_front()

;for

(int i=w+

1;ilength()

;++i)

cout

}

2019 計蒜之道 複賽 D 「星雲系統」

現在給定你乙個字串s以及乙個整數k,請求出s的字典序最小的長度為k的子串行。題目鏈結 第一行乙個由小寫英文本母構成的字串s,第二行乙個正整數k。一行乙個字串ans,表示答案。0helloworld 5ellld 設串長為n,則只需刪掉n k個字元。用乙個單調棧維護,依次將字串的每個字元插入,如果當前...

2019 計蒜之道 複賽 D 「星雲系統」

全世界的中心傳輸節點和各地的網路節點組成的這個 星雲系統 何其複雜。我們現在只考慮一條支線上的網路節點,每乙個網路節點比作乙個字元的話,這條支線就是乙個字串。現在給定你乙個字串 ss 以及乙個整數 kk,請求出 ss 的字典序最小的長度為 kk 的子串行。第一行乙個由小寫英文本母構成的字串 ss,第...

計蒜之道 2019 決賽 摸魚記

聽說決賽考機器學習,而且有7.5小時,就很慌。後來聽說之前那些人都是現場學的,就決定現場學習乙個吧。先看題,大概是個點選量 就是給你一大堆已經有的資料,包括時間 地點 興趣愛好等資料以及是否點選了,又給了一堆資料要你 點選率。去問了一下zjt,他說了一堆東西,但是我都聽不懂。接著就自己上網查了一下,...