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