后缀数组height排序后并查集合并
也就是height较大的合并不影响较小的
num[i]=num[i+1] ans[i]=ans[i+1]
合并时,num+=sz[x]*sz[y],ans=max(mn[x]*mn[y],mx[x]*mx[y],ans)
这种思路适应于求点对,还可以考虑启发式合并
后缀数组还有的常见思路就是二分,height分组
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 300005 4 #define ll long long 5 ll sum[N],ans[N]; 6 int n,val[N],fa[N],mx[N],mn[N],sz[N]; 7 int m=256,c[N],sa[N],rk[N],h[N],t1[N],t2[N]; 8 char s[N]; 9 struct Node{ 10 int h,x,y; 11 }g[N]; 12 int find(int x){ 13 return fa[x]==x?x:fa[x]=find(fa[x]); 14 } 15 void get_sa(int n){ 16 int *x=t1,*y=t2; 17 for(int i=0;i<m;i++)c[i]=0; 18 for(int i=0;i<n;i++)c[x[i]=s[i]]++; 19 for(int i=0;i<m;i++)c[i]+=c[i-1]; 20 for(int i=n-1;i>=0;i--)sa[--c[x[i]]]=i; 21 for(int k=1;k<=n;k<<=1){ 22 int p=0; 23 for(int i=n-k;i<n;i++)y[p++]=i; 24 for(int i=0;i<n;i++)if(sa[i]>=k)y[p++]=sa[i]-k; 25 for(int i=0;i<m;i++)c[i]=0; 26 for(int i=0;i<n;i++)c[x[y[i]]]++; 27 for(int i=0;i<m;i++)c[i]+=c[i-1]; 28 for(int i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i]; 29 swap(x,y);x[sa[0]]=0;p=1; 30 for(int i=1;i<n;i++) 31 x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?p-1:p++; 32 if(p>=n)break; 33 m=p; 34 } 35 } 36 void get_height(int n){ 37 for(int i=0;i<n;i++)rk[sa[i]]=i; 38 int k=0; 39 for(int i=0;i<n;i++){ 40 if(k)k--; 41 int j=sa[rk[i]-1]; 42 while(s[i+k]==s[j+k])k++; 43 h[rk[i]]=k; 44 } 45 } 46 bool cmp(Node x,Node y){ 47 return x.h>y.h; 48 } 49 void unite(int x,int y){ 50 fa[x]=y; 51 sz[y]+=sz[x]; 52 mn[y]=min(mn[y],mn[x]); 53 mx[y]=max(mx[y],mx[x]); 54 } 55 int main(){ 56 scanf("%d",&n); 57 scanf("%s",s); 58 for(int i=1;i<=n;i++)scanf("%d",&val[i]); 59 get_sa(n+1); 60 get_height(n+1); 61 for(int i=1;i<=n;i++)fa[i]=i,sz[i]=1,mx[rk[i-1]]=mn[rk[i-1]]=val[i]; 62 for(int i=1;i<n;i++)g[i].h=h[i+1],g[i].x=i+1,g[i].y=i; 63 sort(g+1,g+n,cmp); 64 memset(sum,128,sizeof(sum)); 65 for(int i=g[1].h,j=1;i>=0;i--){ 66 ans[i]=ans[i+1],sum[i]=sum[i+1]; 67 for(;j<n&&g[j].h==i;j++){ 68 int x=find(g[j].x),y=find(g[j].y); 69 sum[i]=max(sum[i],1ll*mx[x]*mx[y]); 70 sum[i]=max(sum[i],1ll*mn[x]*mn[y]); 71 ans[i]+=1ll*sz[x]*sz[y]; 72 unite(x,y); 73 } 74 } 75 for(int i=0;i<n;i++)printf("%lld %lld\n",ans[i],ans[i]==0?0:sum[i]); 76 return 0; 77 }
时间: 2024-10-11 07:02:20