相似的子串 字尾陣列 二分答案

2021-10-23 05:33:01 字數 1824 閱讀 6690

求k個不相交字元子串的最大相同字首長度x。

很容易往字尾陣列上靠,但是這還不夠,因為很容易就想偏了,這裡,我們想處理乙個是不重疊,乙個是最大的字首相同,於是,不妨設最長字首為x,然後二分這個x,這是因為height的關係具有連續性,所以這樣就能很清晰的劃分出來我們需要進行處理的sa的區間了。

然後我們對於這些字尾的字首下標,我們存進乙個公升序堆內,貪心來選,看看能否有k個以上的滿足條件的不重疊子串,於是二分的判斷條件也就寫出來了。

注意的是,判斷二分x==0的時候,直接返回true,或者從1開始判斷。

9 3

aaaaaaaaa

ans:3

11 3

abababababc

ans:2

9 2dsaasfjai

ans:1

#include #include #include #include #include #include #include #include #include #include #include #include #include //#include //#include #define lowbit(x) ( x&(-x) )

#define pi 3.141592653589793

#define e 2.718281828459045

#define inf 0x3f3f3f3f3f3f3f3f

#define eps 1e-4

#define half (l + r)>>1

#define lsn rt<<1

#define rsn rt<<1|1

#define lson lsn, l, mid

#define rson rsn, mid+1, r

#define ql lson, ql, qr

#define qr rson, ql, qr

#define myself rt, l, r

#define mp(a, b) make_pair(a, b)

using namespace std;

typedef unsigned long long ull;

typedef unsigned int uit;

typedef long long ll;

const int maxn = 2e5 + 7;

struct sa

swap(x, y);

x[sa[1]] = 1; num = 1;

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

if(num == n) break;

m = num;}}

inline void get_height()

}inline void clear()

} sa;

int n, k;

char ch[maxn];

priority_queue, greater> q;

inline bool check(int lim)

}if(num >= k) return true;

}q.push(sa.sa[ith]);

ith++;

}return false;

}int main()

else r = mid - 1;

}printf("%d\n", ans);

return 0;}/*

9 3aaaaaaaaa

ans:3

11 3

abababababc

ans:2

9 2dsaasfjai

ans:1

*/

相似的字串(hash 二分)

題意 給定長為n的字串s,要取出k個位置不相交的字串,取這k個串中任意兩個最長公共字首最小的最為 x 對所有符合條件的k,求出情況最大的x 樣例 思路 求相同字首匹配方式可以通過 進製hash 來處理,同時對於符合條件的長度,使用二分來優化時間複雜度。實際上這裡就運用了 字串hash值的方式,我們設...

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