先把问题放在后缀数组上考虑
已知两个数组a b,求min(a[i],...,a[j])+(b[i]^b[j])的最大值
套路题
初始每个点都是一个小连通块
把a按从大到小的顺序加入,计算当前加入边作为min的贡献:
每次加入会把两个连通块联通,答案就是两边连通块各出一个数能得到的异或和最大值
我:这不是线性基吗
miaom:mdzz,只能有两个数
我:蛤,好难啊,怎么做啊
miaom:Trie啊
我:哦
没了
1 #include <bits/stdc++.h> 2 #define N 500001 3 #define MAX 18 4 using namespace std; 5 int NODE,n;char ch; 6 int a[N],b[N],c[N*MAX][2],size[N],rt[N],lef[N]; 7 pair<int,int> so[N]; 8 int X[N],Y[N],SA[N],Rk[N],Ht[N],v[N]; 9 void GetSA(int a[],int n,int m=256) 10 { 11 int *x=X,*y=Y,i,p,j; 12 memset(v,0,sizeof v); 13 for(i=1;i<=n;i++)v[x[i]=a[i]]++; 14 for(i=1;i<=m;i++)v[i]+=v[i-1]; 15 for(i=n;i>=1;i--)SA[v[x[i]]--]=i; 16 for(i=1;i<=n;i<<=1,m=p) 17 { 18 p=0; 19 memset(v,0,sizeof v); 20 for(j=n-i+1;j<=n;j++)y[++p]=j; 21 for(j=1;j<=n;j++)if(SA[j]>i)y[++p]=SA[j]-i; 22 for(j=1;j<=n;j++)v[x[y[j]]]++; 23 for(j=1;j<=m;j++)v[j]+=v[j-1]; 24 for(j=n;j>=1;j--)SA[v[x[y[j]]]--]=y[j]; 25 swap(x,y); 26 p=1;x[SA[1]]=1; 27 for(j=2;j<=n;j++) 28 if(y[SA[j-1]]==y[SA[j]]&&y[SA[j-1]+i]==y[SA[j]+i]) x[SA[j]]=p; 29 else x[SA[j]]=++p; 30 if(p>=n)break; 31 } 32 } 33 void GetHt(int a[],int n) 34 { 35 int k=0; 36 for(int i=1;i<=n;i++)Rk[SA[i]]=i; 37 for(int i=1;i<=n;i++) 38 { 39 if(k)k--; 40 int j=SA[Rk[i]-1]; 41 while(i+k<=n&&j+k<=n&&a[i+k]==a[j+k])k++; 42 Ht[Rk[i]]=k; 43 } 44 } 45 int build(int x) 46 { 47 int rt=++NODE,now=rt; 48 for(int i=MAX;i>=0;i--) 49 c[now][(x>>i)&1]=++NODE,now=NODE; 50 return rt; 51 } 52 int que(int x,int y,int z=0) 53 { 54 int best=z; 55 if(c[x][0]) 56 if(c[y][1]) best=que(c[x][0],c[y][1],z*2+1); 57 else best=que(c[x][0],c[y][0],z*2); 58 if(c[x][1]) 59 if(c[y][0]) best=max(best,que(c[x][1],c[y][0],z*2+1)); 60 else best=max(best,que(c[x][1],c[y][1],z*2)); 61 return best; 62 } 63 void merge(int x,int y) 64 { 65 if(c[x][0]) 66 if(c[y][0]) merge(c[x][0],c[y][0]); 67 else c[y][0]=c[x][0]; 68 if(c[x][1]) 69 if(c[y][1]) merge(c[x][1],c[y][1]); 70 else c[y][1]=c[x][1]; 71 } 72 int getfa(int x) 73 { 74 if(lef[x]==x) return x; 75 else return lef[x]=getfa(lef[x]); 76 } 77 int main() 78 { 79 scanf("%d",&n); 80 for(ch=getchar();!isalpha(ch);ch=getchar()); 81 for(int i=1;i<=n;i++,ch=getchar()) 82 a[i]=ch; 83 for(int i=1;i<=n;i++) 84 scanf("%d",&b[i]); 85 GetSA(a,n); 86 GetHt(a,n); 87 for(int i=1;i<=n;i++) 88 size[i]=1,lef[i]=i,rt[i]=build(b[SA[i]]); 89 for(int i=2;i<=n;i++) 90 so[i-1]=make_pair(n-Ht[i],i); 91 sort(so+1,so+n); 92 int ret=0; 93 for(int i=1;i<n;i++) 94 { 95 int x=so[i].second,y=x-1,z=n-so[i].first; 96 x=getfa(x);y=getfa(y); 97 if(size[x]<size[y]) swap(x,y); 98 int bes=que(rt[y],rt[x])+z; 99 if(bes>ret) 100 ret=bes; 101 merge(rt[y],rt[x]); 102 size[x]+=size[y]; 103 lef[y]=x; 104 } 105 printf("%d ",ret); 106 return 0; 107 }