没有题面差评
先来遍SA求出h,再给h排序,从大到小计算,并查集维护连续的区间(表达能力太弱。。还是看代码好说话)
1 #include<bits/stdc++.h> 2 #define inc(i,l,r) for(int i=l;i<=r;i++) 3 #define dec(i,l,r) for(int i=l;i>=r;i--) 4 #define link(x) for(edge *j=h[x];j;j=j->next) 5 #define mem(a) memset(a,0,sizeof(a)) 6 #define inf 1e18 7 #define ll long long 8 #define succ(x) (1<<x) 9 #define NM 300000+5 10 using namespace std; 11 ll read(){ 12 ll x=0,f=1;char ch=getchar(); 13 while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} 14 while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); 15 return x*f; 16 } 17 char st[NM]; 18 int n,m,tmp[NM],top[NM],sa[NM],h[NM],rank[NM]; 19 ll f[NM],mx[NM],mn[NM],size[NM],ans[NM],_ans[NM]; 20 bool cmp(int x,int y){ 21 return h[x]>h[y]; 22 } 23 void getsa(){ 24 int j;m=256; 25 inc(i,0,n)top[rank[i]=(int)st[i]]++; 26 inc(i,1,m)top[i]+=top[i-1]; 27 inc(i,0,n)sa[--top[rank[i]]]=i; 28 for(int k=1;k<=n;k<<=1){ 29 inc(i,0,n){ 30 j=sa[i]-k; 31 if(j<0)j+=n+1; 32 tmp[top[rank[j]]++]=j; 33 } 34 // inc(i,0,n)printf("%d ",tmp[i]);printf(" "); 35 sa[tmp[top[0]=0]]=j=0; 36 inc(i,1,n){ 37 if(rank[tmp[i]]!=rank[tmp[i-1]]||rank[tmp[i]+k]!=rank[tmp[i-1]+k]) 38 top[++j]=i; 39 sa[tmp[i]]=j; 40 } 41 memcpy(rank,sa,sizeof(sa)); 42 memcpy(sa,tmp,sizeof(tmp)); 43 } 44 j=0; 45 inc(i,0,n)if(rank[i]){ 46 if(j)j--; 47 while(st[i+j]==st[sa[rank[i]-1]+j])j++; 48 h[rank[i]]=j; 49 } 50 } 51 int find(int x){ 52 return f[x]==x?x:f[x]=find(f[x]); 53 } 54 int main(){ 55 freopen("data.in","r",stdin); 56 n=read(); 57 scanf("%s",st); 58 st[n]='$'; 59 inc(i,0,n-1)mx[i]=mn[i]=read(); 60 getsa(); 61 inc(i,0,n-1)f[i]=i,tmp[i]=i+1,size[i]=1; 62 sort(tmp+1,tmp+n+1,cmp); 63 inc(i,0,n-1)_ans[i]=-inf; 64 // inc(i,1,n)printf("%d ",h[tmp[i]]);printf(" "); 65 inc(i,1,n){ 66 int x=find(sa[tmp[i]]),y=find(sa[tmp[i]-1]); 67 if(x==y)continue; 68 ans[h[tmp[i]]]+=(ll)size[x]*size[y]; 69 _ans[h[tmp[i]]]=max(_ans[h[tmp[i]]],max((ll)mx[x]*mx[y],(ll)mn[x]*mn[y])); 70 f[y]=x;size[x]+=size[y]; 71 mx[x]=max(mx[x],mx[y]); 72 mn[x]=min(mn[x],mn[y]); 73 } 74 dec(i,n-2,0)if(ans[i+1])ans[i]+=ans[i+1],_ans[i]=max(_ans[i],_ans[i+1]); 75 inc(i,0,n-1)if(!ans[i])_ans[i]=0; 76 inc(i,0,n-1)printf("%lld %lld ",ans[i],_ans[i]); 77 return 0; 78 }