bzoj 4556: [Tjoi2016&Heoi2016]字符串
Posted SD_le
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 4556: [Tjoi2016&Heoi2016]字符串相关的知识,希望对你有一定的参考价值。
二分ans,二分区间长度,st表查,最后主席树判断。
这题最大收获学到了一个nb的卡常技巧,主席树元素个数为0直接返回,不敢相信快了一倍。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #define N 200005 6 using namespace std; 7 inline int read() 8 { 9 int p=0;char c=getchar(); 10 while(c<‘0‘||c>‘9‘)c=getchar(); 11 while(c>=‘0‘&&c<=‘9‘)p=p*10+c-‘0‘,c=getchar(); 12 return p; 13 } 14 int wb[N],rank[N],sa[N],sum[N]; 15 int mnn(int x,int y) 16 { 17 if(x<y)return x;return y; 18 } 19 char s[N]; 20 void da(int n,int m) 21 { 22 int *x=rank,*y=wb; 23 for(int i=0;i<m;i++)sum[i]=0; 24 for(int i=0;i<n;i++)sum[x[i]=s[i]]++; 25 for(int i=1;i<m;i++)sum[i]+=sum[i-1]; 26 for(int i=n-1;i>=0;i--)sa[--sum[x[i]]]=i; 27 int p=1; 28 for(int j=1;p<n;j<<=1,m=p) 29 { 30 p=0; 31 for(int i=n-j;i<n;i++)y[p++]=i; 32 for(int i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j; 33 for(int i=0;i<m;i++)sum[i]=0; 34 for(int i=0;i<n;i++)sum[x[i]]++; 35 for(int i=1;i<m;i++)sum[i]+=sum[i-1]; 36 for(int i=n-1;i>=0;i--)sa[--sum[x[y[i]]]]=y[i]; 37 swap(x,y);x[sa[0]]=0;p=1; 38 for(int i=1;i<n;i++) 39 x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i-1]+j]==y[sa[i]+j]?p-1:p++; 40 } 41 return ; 42 } 43 int h[N]; 44 void cal(int n) 45 { 46 int k=0; 47 for(int i=1;i<=n;i++)rank[sa[i]]=i; 48 for(int i=0;i<n;i++) 49 { 50 if(k)k--; 51 int j=sa[rank[i]-1]; 52 while(s[j+k]==s[i+k])k++; 53 h[rank[i]]=k; 54 } 55 } 56 int n,m; 57 int mn[N][20]; 58 int lg[N]; 59 int root[N]; 60 void st() 61 { 62 int now=0; 63 for(int i=1;i<=n;i<<=1) 64 { 65 for(int j=i;j<i<<1;j++) 66 { 67 lg[j]=now; 68 } 69 now++; 70 } 71 for(int i=1;i<=n;i++)mn[i][0]=h[i]; 72 for(int i=1;i<=18;i++) 73 { 74 int k=(1<<(i-1)); 75 for(int j=1;j<=n;j++) 76 { 77 if(j+k<=n)mn[j][i]=mnn(mn[j][i-1],mn[j+k][i-1]); 78 else mn[j][i]=mn[j][i-1]; 79 } 80 }return ; 81 } 82 struct node 83 { 84 int l,r,sum; 85 }a[N*20];int cnt; 86 void merge(int x,int y,int l,int r,int pos) 87 { 88 if(l==r) 89 { 90 a[x].sum=1; 91 return ; 92 } 93 int mid=(l+r)>>1; 94 if(pos<=mid) 95 { 96 a[x].l=++cnt; 97 a[x].r=a[y].r; 98 merge(a[x].l,a[y].l,l,mid,pos); 99 } 100 else 101 { 102 a[x].r=++cnt; 103 a[x].l=a[y].l; 104 merge(a[x].r,a[y].r,mid+1,r,pos); 105 } 106 a[x].sum=a[a[x].l].sum+a[a[x].r].sum; 107 } 108 bool qur(int x,int y,int l,int r,int ll,int rr) 109 { 110 if(a[x].sum==a[y].sum)return 0; 111 if(l>=ll&&r<=rr)return a[x].sum!=a[y].sum; 112 int mid=(l+r)>>1; 113 if(ll<=mid)if(qur(a[x].l,a[y].l,l,mid,ll,rr))return 1; 114 if(rr>mid)if(qur(a[x].r,a[y].r,mid+1,r,ll,rr))return 1; 115 return 0; 116 } 117 int t1,t2,t3,t4; 118 inline int qr(int l,int r) 119 { 120 if(l>r)return N; 121 int k=lg[r-l+1]; 122 return mnn(mn[l][k],mn[r-(1<<k)+1][k]); 123 } 124 bool pan(int x) 125 { 126 int pos=rank[t3-1]; 127 int ll,rr; 128 int l=pos,r=n,mid; 129 while(l<=r) 130 { 131 mid=(l+r)>>1; 132 if(qr(pos+1,mid)<x)r=mid-1; 133 else l=mid+1; 134 } 135 rr=r; 136 l=1,r=pos; 137 while(l<=r) 138 { 139 mid=(l+r)>>1; 140 if(qr(mid+1,pos)<x)l=mid+1; 141 else r=mid-1; 142 } 143 ll=l; 144 return qur(root[rr],root[ll-1],1,n,t1,t2-x+1); 145 } 146 147 int main() 148 { 149 scanf("%d%d",&n,&m); 150 scanf("%s",s); 151 da(n+1,256);cal(n); 152 st(); 153 for(int i=1;i<=n;i++) 154 { 155 root[i]=++cnt; 156 merge(root[i],root[i-1],1,n,sa[i]+1); 157 } 158 for(int i=1;i<=m;i++) 159 { 160 t1=read();t2=read();t3=read();t4=read(); 161 int l=0;int r=min(t2-t1+1,t4-t3+1); 162 while(l<=r) 163 { 164 int mid=(l+r)>>1; 165 if(pan(mid))l=mid+1; 166 else r=mid-1; 167 } 168 printf("%d\n",r); 169 } 170 return 0; 171 } 172 /* 173 5 2 174 ababaa 175 1 4 2 5 176 1 4 2 3 177 */
以上是关于bzoj 4556: [Tjoi2016&Heoi2016]字符串的主要内容,如果未能解决你的问题,请参考以下文章
Bzoj4556: [Tjoi2016&Heoi2016]字符串 后缀数组
[BZOJ4556][Tjoi2016&Heoi2016]字符串 后缀数组+主席树
[BZOJ4556][TJOI2016&&HEOI2016]字符串(二分答案+后缀数组+RMQ+主席树)
bzoj 4556: [Tjoi2016&Heoi2016]字符串