悬赏关注*1!后缀数组 SA 10pts 求调!
查看原帖
悬赏关注*1!后缀数组 SA 10pts 求调!
307603
_cmh楼主2022/8/17 18:47

写了一下午,交了 20+ 发,10pts……

#include<bits/stdc++.h>
using namespace std;

const int N=1e6+3;
int n,m,T,w,now,tot,a[N],sa[N],rk[N<<1],_rk[N<<1],id[N],cnt[N],height[N],sta[N],q;
bool vis[N];
stack<int>s;

void SA(){
	m=114514;
	for(int i=1;i<=n;i++) cnt[rk[i]=a[i]]++;
	for(int i=1;i<=m;i++) cnt[i]+=cnt[i-1];
	for(int i=n;i;i--) sa[cnt[rk[i]]--]=i;
	for(w=1;w<n;w<<=1,m=now){
		now=0;
		for(int i=n;i>n-w;i--) id[++now]=i;
		for(int i=1;i<=n;i++) if(sa[i]>w) id[++now]=sa[i]-w;
		memset(cnt,0,sizeof(cnt));
		for(int i=1;i<=n;i++) cnt[rk[id[i]]]++;
		for(int i=1;i<=m;i++) cnt[i]+=cnt[i-1];
		for(int i=n;i;i--) sa[cnt[rk[id[i]]]--]=id[i];
		memcpy(_rk,rk,sizeof(rk));
		now=0;
		for(int i=1;i<=n;i++) rk[sa[i]]=now+=!(_rk[sa[i]]==_rk[sa[i-1]]&&_rk[sa[i]+w]==_rk[sa[i-1]+w]);
		if(now>n) break;
	}
	for(int k=0,i=1;i<=n;i++){
		if(k) k--;
		while(a[i+k]==a[sa[rk[i]-1]+k]) k++;
		height[rk[i]]=k;
	}
}

bool check(int x){
	while(!s.empty()) vis[s.top()]=0,s.pop();
	for(int i=1;i<=n;i++){
		if(height[i]<x) while(!s.empty()) vis[s.top()]=0,s.pop();
		if(!vis[id[sa[i]]]){
			vis[id[sa[i]]]=1;
			s.push(id[sa[i]]);
			if(s.size()>=T) return 1; 
		}
	}
	return 0;
}

int main(){
	scanf("%d",&T); int qwq=1865;
	for(int i=1;i<=T;i++){
		int x,lst=0; scanf("%d",&x);
		while(x--){
			int y; scanf("%d",&y);
			a[++n]=y-lst; lst=y;
		}
		a[++n]=qwq++;
	}
	SA();
	int l=0,r=n,ans=0;
	while(l<=r){
		int mid=(l+r)>>1;
		if(check(mid)) l=mid+1,ans=mid;
		else r=mid-1;
	}
	printf("%d",ans+1);
}

求调。

2022/8/17 18:47
加载中...