bzoj4199&uoj131: [Noi2015]品酒大会
思路:先求出height,然后根据排名重新给后缀标号,按height从大到小做,每次合并i和i-1,用并查集维护,更新答案。
#include<cstdio> #include<cstring> #include<algorithm> #define max(a,b) (a>b?a:b) #define min(a,b) (a<b?a:b) const int maxn=300010; using namespace std; typedef long long ll; int n,a[maxn];ll ans[maxn],cnt[maxn];char s[maxn]; struct orz{int h,pos;}cls[maxn]; bool cmp(orz a,orz b){return a.h>b.h;} struct Tufs{ int maxs[maxn],mins[maxn],fa[maxn],siz[maxn]; int getfa(int x){return x==fa[x]?x:fa[x]=getfa(fa[x]);} void merge(int x,int y){ x=getfa(x),y=getfa(y),fa[y]=x; maxs[x]=max(maxs[x],maxs[y]); mins[x]=min(mins[x],mins[y]); siz[x]+=siz[y]; } }ufs; struct Suffix_Array{ int sa[maxn],rank[maxn],t1[maxn],t2[maxn],sum[maxn],h[maxn]; void getsa(){ int *x=t1,*y=t2,m=255,p=0; for (int i=1;i<=n;i++) sum[x[i]=s[i]]++; for (int i=1;i<=m;i++) sum[i]+=sum[i-1]; for (int i=n;i;i--) sa[sum[x[i]]--]=i; for (int j=1;p<n;j<<=1,m=p){ p=0; for (int i=n-j+1;i<=n;i++) y[++p]=i; for (int i=1;i<=n;i++) if (sa[i]>j) y[++p]=sa[i]-j; memset(sum,0,sizeof(sum)); for (int i=1;i<=n;i++) sum[x[y[i]]]++; for (int i=1;i<=m;i++) sum[i]+=sum[i-1]; for (int i=n;i;i--) sa[sum[x[y[i]]]--]=y[i]; swap(x,y),x[sa[1]]=p=1; for (int i=2;i<=n;i++){ if (y[sa[i]]!=y[sa[i-1]]||y[sa[i]+j]!=y[sa[i-1]+j]) p++; x[sa[i]]=p; } } memcpy(rank,x,sizeof(rank)); } void geth(){ for (int i=1,j=0;i<=n;i++){ if (rank[i]==1) continue; while (s[i+j]==s[sa[rank[i]-1]+j]) j++; h[rank[i]]=j; if (j) j--; } } void work(){ memset(ans,128,sizeof(ans)); for (int i=2;i<=n;i++) cls[i-1]=(orz){h[i],i}; sort(cls+1,cls+n,cmp); for (int i=cls[1].h,j=1;i>=0;i--){ ans[i]=ans[i+1],cnt[i]=cnt[i+1]; for (;j<n&&cls[j].h==i;j++){ int x=ufs.getfa(cls[j].pos),y=ufs.getfa(cls[j].pos-1); ans[i]=max(ans[i],1ll*ufs.maxs[x]*ufs.maxs[y]); ans[i]=max(ans[i],1ll*ufs.mins[x]*ufs.mins[y]); cnt[i]+=1ll*ufs.siz[x]*ufs.siz[y]; ufs.merge(x,y); } } for (int i=0;i<n;i++) if (cnt[i]) printf("%lld %lld\n",cnt[i],ans[i]); else puts("0 0"); } }SA; int main(){ scanf("%d%s",&n,s+1); for (int i=1;i<=n;i++) scanf("%d",&a[i]); SA.getsa(),SA.geth(); for (int i=1;i<=n;i++) ufs.fa[i]=i,ufs.mins[SA.rank[i]]=ufs.maxs[SA.rank[i]]=a[i],ufs.siz[i]=1; SA.work(); return 0; }