94分WA#2求调 想法是单调队列
查看原帖
94分WA#2求调 想法是单调队列
749301
AmiyaCast楼主2024/1/19 13:15

想法是先求出h数组 然后对于每一个排名的后缀标记位置(属于哪一个串,就是那个col数组) 然后采用单调队列,每一次维护一个合法子区间:区间内包括所有的类型的col 但是WA #2

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
#include<map>
#include<queue>
#include<algorithm>
#define ll int 
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=b;i>=a;--i)
using namespace std;
inline ll read()
{
    ll x=0,f=1;
    char c=getchar();
    while (c<'0' || c>'9')
    {
        if (c=='-')  f=-1;
        c=getchar();
    }
    while (c>='0' && c<='9')
    {
        x=x*10+c-'0';
         c=getchar();
    }
    return x*f;
}

inline void print(ll x)
{
	if(x < 0) putchar('-'), x = -x;
	if(x > 9) print(x / 10);
	putchar(x % 10 + '0');
	return ;
}
const int N = 1e5 + 7;
int rk[N << 1], sa[N], n, lstrk[N << 1], lstsa[N], w, m = 127, cnt[N], h[N], f[N][20];
char s[N << 1], s1[N << 1];


#define siz n * sizeof(int)
void init(){
	m = 127;
	memset(cnt, 0, sizeof cnt);
	memset(sa, 0, siz);
	memset(rk, 0, siz);
	memset(h, 0, siz);
	for(int i = 1; i <= n; ++i) ++cnt[rk[i] = s[i]];
	for(int i = 1; i <= m; ++i) cnt[i] += cnt[i - 1];
	for(int i = n; i >= 1; --i) sa[cnt[rk[i]]--] = i;
	memcpy(lstrk + 1, rk + 1, siz);
	for(int p = 0, i = 1; i <= n; ++i)
		if(lstrk[sa[i]] == lstrk[sa[i - 1]])
			rk[sa[i]] = p;
		else
			rk[sa[i]] = ++p;
	for(w = 1; w < n; w <<= 1, m = n){
		for(int p = 0, i = n; i >= n - w + 1; --i) lstsa[++p] = i;
		for(int p = w, i = 1; i <= n; ++i)
			if(sa[i] > w)  lstsa[++p] = sa[i] - w; 
		memset(cnt, 0, sizeof cnt);
		for(int i = 1; i <= n; ++i) ++cnt[rk[lstsa[i]]];
		for(int i = 1; i <= m; ++i) cnt[i] += cnt[i - 1];
		for(int i = n; i >= 1; --i) sa[cnt[rk[lstsa[i]]]--] = lstsa[i];
		memcpy(lstrk + 1, rk + 1, siz);
		for(int p = 0, i = 1; i <= n; ++i)
			if(lstrk[sa[i]] == lstrk[sa[i - 1]] && lstrk[sa[i] + w] == lstrk[sa[i - 1] + w])
				rk[sa[i]] = p;
			else
				rk[sa[i]] = ++p;
	}
	for(int i = 1, k = 0; i <= n; ++i){
		if(rk[i] == 0) continue;
		if(k) --k;
		while(s[i + k] == s[sa[rk[i] - 1] + k]) ++k;
		h[rk[i]] = k;
	}
}
ll q[N] = {0}, hd = 0, tl = 0;
char S[10][3000];
int d[10];
int col[N];

void push(ll x){
	while(tl > hd && h[q[tl]] > h[x]) tl--;
	q[++tl] = x;
	cnt[col[x]]++;
}
ll ans = 0;

void checkcnt(){
	cout << "cnt: ";
	for(int i = 1; i <= 5; ++i)
		cout << cnt[i] << " "; puts("");
}
void checkqueue(){
	cout << "queue: ";
	for(int opt = hd + 1; opt <= tl; ++opt)
		cout << q[opt] << " "; puts("");
}
ll l, r;
void cut(int x){
	while(q[hd + 1] < x){
		++hd;
	}
}
int main(){
	int T = read();
	for(int i = 1; i <= T; ++i)
		scanf("%s", S[i] + 1);
	for(int i = 1; i <= T; ++i)
		strcat(s + 1, S[i]+ 1), d[i] = strlen(s + 1);
	n = strlen(s + 1);
	if(T == 1){
		print(n);
		return 0;
	}
	init();
	memset(cnt, 0, sizeof cnt);
	for(int i = 1; i <= n; ++i){
		for(int k = 1; k <= T; ++k){
			if(sa[i] > d[k - 1] && sa[i] <= d[k])
				col[i] = k;
		}
	}

	q[++tl] = 2;
	++cnt[col[1]];
	++cnt[col[2]];
	int i, tmp;
	for(i = 3, tmp = (col[1] != col[2]) + 1; i <= n, tmp < T; ++i){
		push(i);
		if(cnt[col[i]] == 1) tmp++;
	}
	
	for(l = 2, r = i - 1; ;++l){
		cut(l); 
		ans = max(ans, h[q[hd + 1]]);
		-- cnt[col[l - 1]];
		int suc = 1;
		if(cnt[col[l - 1]] == 0){
			suc = 0;
			for(r = r + 1; r <= n; ++r){
				push(r);
				if(col[r] == col[l - 1]){
					suc = 1;
					break;
				}
			}
		}
		if(!suc)  break;
	}
	
	print(ans); puts("");

	return 0;
}

2024/1/19 13:15
加载中...