題意:
現在給定你乙個字串 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,他說了一堆東西,但是我都聽不懂。接著就自己上網查了一下,...