BZOJ4310 跳蚤 字尾陣列 二分

2022-05-24 23:09:08 字數 1409 閱讀 9604

很久很久以前,森林裡住著一群跳蚤。一天,跳蚤國王得到了乙個神秘的字串,它想進行研究。首先,他會把串

分成不超過 k 個子串,然後對於每個子串 s,他會從s的所有子串中選擇字典序最大的那乙個,並在選出來的k個子串中選擇字典序最大的那乙個。他稱其為「魔力串」。現在他想找乙個最優的分法讓「魔力串」字典序最小。

第一行乙個整數 k,k<=15

接下來乙個長度不超過 10^5 的字串 s。

輸出一行,表示字典序最小的「魔力串」。

2ababa

ba//解釋:

分成aba和ba兩個串,其中字典序最大的子串為ba

首先我們要讓所有段的最大子串的最大串最小,然後就可以考慮用二分,因為有一大堆子串的操作

不難想到字尾陣列

然後就可以考慮怎麼check

我們從後向前貪心

每次因為只需要向前擴充套件乙個位置,所以每次只用檢查乙個子串是不是大於當前二分出的串

然後就可以很方便地做出來了

height處理的時候老是要寫錯

然後求lcp的時候注意把左區間的指標右移,並且要特判兩個串的起始位置相等的情況

然後是貪心的時候每一段最後乙個字元一定要特判

#includeusing namespace std;

typedef pairpi;

typedef long long ll;

const int n = 1e5 + 10;

const int log = 20;

struct suffix_array

} void radix_sort()

void buildsa()

} void buildrank()

void buildrank_pre()

void buildheight()

} void buildst()

}}

int queryst(int l, int r)

int querylcp(int la, int ra, int lb, int rb)

//return substringa <= substringb

bool cmpsubstring(int la, int ra, int lb, int rb)

pi findkth(ll k)

} sa;

int k, len;

char c[n];

bool check(pi cur)

} return ++tot <= k;

}int main() else l = mid + 1;

} for (int i = ans.first; i <= ans.second; i++) putchar(c[i]);

return 0;

}

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 ...

BZOJ4310 跳蚤 字尾陣列 ST表 二分

趕緊寫完,就能快點回去洗澡了 bzoj4310傳送門 給乙個長度不超過100000的字串。現在要把這個字串分成k組 k不超過length 然後對於每一組,取其字典序最大的子串,得到乙個集合s,記s中字典序最大的那個串為ss,詢問ss字典序最小可以是什麼 輸入格式 第一行乙個整數k,含義如題 接下來一...