萌新刚学后缀数组求助
查看原帖
萌新刚学后缀数组求助
73032
日居月诸lucejx楼主2021/1/25 15:26

不知为什么,过不去 #5 和 #9。

已经选了题解的三篇代码各拍了 1w 次,但是没有发现问题。

大致思路是:先求后缀数组和height,并且用st表维护sa的最值,最后二分+分段判断。

希望各位大佬帮个忙啊/kel

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
char In[1 << 20], *ss = In, *tt = In;
#define getchar() (ss == tt && (tt = (ss = In) + fread(In, 1, 1 << 20, stdin), ss == tt) ? EOF : *ss++)
ll read() {
	ll x = 0, f = 1; char ch = getchar();
	for(; ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') f = -1;
	for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + int(ch - '0');
	return x * f;
}
const int MAXN = 5005;
int n;
int s[MAXN], d[MAXN];
int sa[MAXN], rk[MAXN], ht[MAXN], mx[MAXN][20], mn[MAXN][20], lg[MAXN], x[MAXN], y[MAXN << 1], c[MAXN];
void SuffixSort() {
	int m = 300;
	for(int i = 1; i <= n; i++) c[x[i] = d[i]]++;
	for(int i = 2; i <= m; i++) c[i] += c[i-1];
	for(int i = n; i >= 1; i--) sa[c[x[i]]--] = i;
	for(int k = 1; k <= n; k <<= 1) {
		int num = 0;
		for(int i = n-k+1; i <= n; i++) y[++num] = i;
		for(int i = 1; i <= n; i++) if(sa[i] > k) y[++num] = sa[i] - k;
		for(int i = 1; i <= m; i++) c[i] = 0;
		for(int i = 1; i <= n; i++) c[x[i]]++;
		for(int i = 2; i <= m; i++) c[i] += c[i-1];
		for(int i = n; i >= 1; i--) sa[c[x[y[i]]]--] = y[i], y[i] = 0;
		for(int i = 1; i <= n; i++) swap(x[i], y[i]);
		x[sa[1]] = num = 1;
		for(int i = 2; i <= n; i++)
			x[sa[i]] = (y[sa[i]] == y[sa[i-1]] && y[sa[i] + k] == y[sa[i-1] + k]) ? num : ++num;
		m = num;
		if(num == n) break;
	}
}
void GetHeight() {
	for(int i = 1; i <= n; i++) rk[sa[i]] = i;
	for(int i = 1, k = 0; i <= n; i++) {
		if(k) k--;
		if(rk[i] == 1) {ht[i] = 0; continue;}
		int j = sa[rk[i] - 1];
		while(i+k <= n && j+k <= n && d[i+k] == d[j+k]) k++;
		ht[rk[i]] = k;
	}
}
void st_init() {
	for(int i = 1; i <= n; i++) mx[i][0] = mn[i][0] = sa[i];
	for(int k = 1; (1 << k) <= n; k++) 
		for(int i = 1; i + (1 << k) - 1 <= n; i++)
			mx[i][k] = max(mx[i][k-1], mx[i + (1 << (k-1))][k-1]),
			mn[i][k] = min(mn[i][k-1], mn[i + (1 << (k-1))][k-1]);
	lg[0] = -1;
	for(int i = 1; i <= n; i++) lg[i] = lg[i >> 1] + 1;
}
int qry_max(int l, int r) {
	int k = lg[r - l + 1];
	return max(mx[l][k], mx[r - (1 << k) + 1][k]);
}
int qry_min(int l, int r) {
	int k = lg[r - l + 1];
	return min(mn[l][k], mn[r - (1 << k) + 1][k]);
}
bool check(int k) {
	int ans = 0;
	for(int l = 1, r = 1; l <= n; l = ++r) {
		while(r+1 <= n && ht[r+1] >= k) r++;
		ans = max(ans, qry_max(l, r) - qry_min(l, r));
	}
	return ans >= k+1;
}
int main() {
	n = read();
	for(int i = 1; i <= n; i++) s[i] = read();
	n--;
	for(int i = 1; i <= n; i++) d[i] = s[i+1] - s[i] + 88;
	SuffixSort();
	GetHeight();
	st_init();
	int ans = -1, l = 0, r = n;
	while(l <= r) {
		int x = (l + r) >> 1;
		if(check(x)) {ans = x; l = x+1;}
		else r = x-1;
	}
	if(ans < 4) printf("0\n");
	else printf("%d\n", ans+1);
	return 0;
}
2021/1/25 15:26
加载中...