題解 bzoj4310跳蚤 SA

2022-02-23 18:45:42 字數 1116 閱讀 2715

cao 還有二分字典序這種操作。。。。

問題性質顯然滿足二分性,但是我們只能對數進行二分,但是如果可以根據乙個數確定乙個字串就好了。

用sa可以實現,根據乙個整數x,可以在\(o(\min (n,ans))\),得到字典序在所有子串中x位的那個串具體是什麼。

二分完之後就是貪心了,從後往前列舉每個位置要不要斷開,現在問題就變成了乙個母串中有兩個子串要比較字典序,也是sa+倍增就行了。

貪心時可以發現,直接在當前位置的後面斷開最優,因為這樣分出來的字典序更小。

//@winlere

#include#include#include#includeusing namespace std;

typedef long long ll;

const int maxn=1e5+5;

void suf_sort(char*str,int*rk,int*sa,int*h,int n)

for(int t=1;t<=n;++t) ++b[rk[t]];

for(int t=1;t<=m;++t) b[t]+=b[t-1];

for(int t=n;t;--t) sa[b[rk[temp[t]]]--]=temp[t];

memset(b+1,0,m<<2); memcpy(temp+1,rk+1,n<<2);

rk[sa[1]]=1;

for(int t=2;t<=n;++t)

rk[sa[t]]=temp[sa[t]]==temp[sa[t-1]]&&temp[sa[t]+l]==temp[sa[t-1]+l]?rk[sa[t-1]]:rk[sa[t-1]]+1;

m=rk[sa[n]];

} for(int t=1,p=0;t<=n;++t)

}int rk[maxn],sa[maxn],st[21][maxn],lg[maxn],n,k;

char c[maxn];

pairgetkth(ll k)

int _que(int l,int r)

bool isnotmore(paira,pairb)

bool chek(ll mid)

return ret<=k;

}int main()

BZOJ4310 跳蚤 字尾陣列 二分

很久很久以前,森林裡住著一群跳蚤。一天,跳蚤國王得到了乙個神秘的字串,它想進行研究。首先,他會把串 分成不超過 k 個子串,然後對於每個子串 s,他會從s的所有子串中選擇字典序最大的那乙個,並在選出來的k個子串中選擇字典序最大的那乙個。他稱其為 魔力串 現在他想找乙個最優的分法讓 魔力串 字典序最小...

BZOJ4310 跳蚤(字尾陣列 二分答案)

傳送門 dar kbzo jdarkbzoj darkbz oj上題面有誤,應該是最大的最小 考慮二分這個最小的串x xx的排名k kk那麼也就是說所有排名比這個大的一定要被切開 考慮乙個字尾s p n s p,n s p,n 如果l cp s p n x 0 lcp s p,n x 0 lcp s...

BZOJ4310 跳蚤(字尾陣列 二分答案)

注意到答案一定是原串的子串,於是考慮造出sa,二分答案是第幾小的子串。第k小子串很容易在sa上求出。之後計算使他成為最大子串至少要在幾個位置切割,對每個字典序比答案大的字尾,找到所有合法切割位置 求lcp即可 就轉化成了選最少的點使每個區間都包含至少乙個點的經典問題。include include ...