"BZOJ4556" string (suffix array, Chairman tree) facet
Bzoj
Exercises
Attention to the question:
Required is \ ([a,b]\) substring and [c,d] \ (lcp\) maximum value
Let's start with the violence.
After finding \ (sa\)
The suffix between brute force enumeration \ ([a,b]\)
Ask for a \ (lcp\)
Complexity \ (O (nm) \)
\ (40\)
#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <algorithm>#include <set>#include <map>#include <vector>#include <queue>using namespaceStd#define LL Long Long#define RG Register#define MAX 222222inline intRead () {RGintx=0, t=1; RgCharCh=getchar (); while((ch<' 0 '|| Ch>' 9 ') &&ch!='-') Ch=getchar ();if(ch=='-') t=-1, Ch=getchar (); while(ch<=' 9 '&&ch>=' 0 ') x=x*Ten+ch-48, Ch=getchar ();returnX*t;}intLg[max],a[max];CharS[max];intN,m;structsa{intX[max],y[max],sa[max],t[max];intht[max],rk[max],p[ -][max];BOOLcmpintIintJintK) {returnY[I]==Y[J]&&Y[I+K]==Y[J+K];}voidGetsa () {intm= -; for(intI=1; i<=n;++i) t[x[i]=a[i]]++; for(intI=1; i<=m;++i) T[i]+=t[i-1]; for(intI=n;i;--i) sa[t[x[i]]--]=i; for(intk=1; k<=n;k<<=1) {intp=0; for(intI=n-k+1; i<=n;++i) y[++p]=i; for(intI=1; i<=n;++i)if(sa[i]>k) Y[++p]=sa[i]-k; for(intI=0; i<=m;++i) t[i]=0; for(intI=1; i<=n;++i) t[x[y[i]]]++; for(intI=1; i<=m;++i) T[i]+=t[i-1]; for(inti=n;i>=1;----) sa[t[x[y[i]]]--]=y[i]; Swap (x, y); x[sa[1]]=p=1; for(intI=2; i<=n;++i) x[sa[i]]=cmp (sa[i],sa[i-1],k)? p:++p;if(p>=n) Break; M=p; } for(intI=1; i<=n;++i) rk[sa[i]]=i; for(intI=1, j=0; i<=n;++i) {if(j)--j; while(A[i+j]==a[sa[rk[i]-1]+J]) ++j; Ht[rk[i]]=j; } }voidPrepare () { for(intI=1; i<=n;++i) p[0][i]=ht[i]; for(intj=1;j< -; ++j) for(intI=1; i<=n;++i) P[j][i]=min (p[j-1][i],p[j-1][i+ (1<< (J-1))]); }intRmqintLintR) {returnMin (p[lg[r-l+1]][l],p[lg[r-l+1]][r-(1<<lg[r-l+1])+1]);}intLcpintLintR) {if(L==R)returnN-l+1;if(Rk[l]>rk[r]) swap (L,R);returnRMQ (Rk[l]+1, Rk[r]); }}sa;intMain () {n=read (); M=read (); scanf"%s", S+1); for(intI=2; i<=n;++i) lg[i]=lg[i>>1]+1; for(intI=1; i<=n;++i) A[i]=s[i]-96; Sa. Getsa (); Sa.prepare (); while(m--) {intA=read (), B=read (), C=read (), D=read ();intans=0; for(intI=a;i<=b;++i) Ans=max (ans,min (min (d-c+1, B-i+1), SA.LCP (i,c)); printf"%d\n", ans); }return 0;}
I'm a real piece of crap.
Won't do
After you have determined \ (c\)
A two-part answer \ (mid\)
Then, you can determine that \ (rank\) must exist within a range \ ([a,b]\)
Then, two to meet \ (lcp\) greater than \ (mid\) of the interval
Then query whether the condition is met
Query using the Chairman tree to do
#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <algorithm>#include <set>#include <map>#include <vector>#include <queue>using namespaceStd#define LL Long Long#define RG Register#define MAX 222222inline intRead () {RGintx=0, t=1; RgCharCh=getchar (); while((ch<' 0 '|| Ch>' 9 ') &&ch!='-') Ch=getchar ();if(ch=='-') t=-1, Ch=getchar (); while(ch<=' 9 '&&ch>=' 0 ') x=x*Ten+ch-48, Ch=getchar ();returnX*t;}intLg[max],a[max];CharS[max];intN,m;structpresident_segment_tree{structNode {intLs,rs;intV }t[max<<5];intTot,rt[max];voidModify (int&now,intFfintLintRintPintW) {now=++tot;t[now]=t[ff];t[now].v+=w;if(L==R)return;intMid= (l+r) >>1;if(P<=mid) Modify (T[NOW].LS,T[FF].LS,L,MID,P,W);ElseModify (T[now].rs,t[ff].rs,mid+1, r,p,w); }intQuery (intR1,intR2,intLintRintLintR) {if(L<=L&&R<=R) {returnT[R2].V-T[R1].V;}intMid= (l+r) >>1, ret=0;if(L<=mid) Ret+=query (t[r1].ls,t[r2].ls,l,mid,l,r);if(R>mid) Ret+=query (t[r1].rs,t[r2].rs,mid+1, r,l,r);returnRet }}seg;structsa{intX[max],y[max],sa[max],t[max];intht[max],rk[max],p[ -][max];BOOLcmpintIintJintK) {returnY[I]==Y[J]&&Y[I+K]==Y[J+K];}voidGetsa () {intm= -; for(intI=1; i<=n;++i) t[x[i]=a[i]]++; for(intI=1; i<=m;++i) T[i]+=t[i-1]; for(intI=n;i;--i) sa[t[x[i]]--]=i; for(intk=1; k<=n;k<<=1) {intp=0; for(intI=n-k+1; i<=n;++i) y[++p]=i; for(intI=1; i<=n;++i)if(sa[i]>k) Y[++p]=sa[i]-k; for(intI=0; i<=m;++i) t[i]=0; for(intI=1; i<=n;++i) t[x[y[i]]]++; for(intI=1; i<=m;++i) T[i]+=t[i-1]; for(inti=n;i>=1;----) sa[t[x[y[i]]]--]=y[i]; Swap (x, y); x[sa[1]]=p=1; for(intI=2; i<=n;++i) x[sa[i]]=cmp (sa[i],sa[i-1],k)? p:++p;if(p>=n) Break; M=p; } for(intI=1; i<=n;++i) rk[sa[i]]=i; for(intI=1, j=0; i<=n;++i) {if(j)--j; while(A[i+j]==a[sa[rk[i]-1]+J]) ++j; Ht[rk[i]]=j; } }voidPrepare () { for(intI=1; i<=n;++i) p[0][i]=ht[i]; for(intj=1;j< +; ++j) for(intI=1; i<=n;++i) P[j][i]=min (p[j-1][i],p[j-1][i+ (1<< (J-1))]); }intRmqintLintR) {if(L==R)return 1e9; ++l;returnMin (p[lg[r-l+1]][l],p[lg[r-l+1]][r-(1<<lg[r-l+1])+1]); }BOOLCheckintLenintAintBintCintD) {intL,R,L=RK[C],R=RK[C]; L=1, R=rk[c]; while(L<r) {intMid= (l+r) >>1;if(RMQ (Mid,rk[c]) >=len) R=mid;ElseL=mid+1; } l=l; L=rk[c],r=n; while(L<r) {intMid= (l+r+1) >>1;if(RMQ (Rk[c],mid) >=len) L=mid;ElseR=mid-1; } r=l;returnSeg. Query (seg.rt[l-1],seg.rt[r],1, N,a,b-len+1); }}sa;intMain () {n=read (); M=read (); scanf"%s", S+1); for(intI=2; i<=n;++i) lg[i]=lg[i>>1]+1; for(intI=1; i<=n;++i) A[i]=s[i]-96; Sa. Getsa (); Sa.prepare (); for(intI=1; i<=n;++i) seg. Modify (seg.rt[i],seg.rt[i-1],1, N,sa.sa[i],1); while(m--) {intA=read (), B=read (), C=read (), D=read ();intans=0;intL=0, R=min (B-A,D-C)+1; while(L<=R) {intMid= (l+r) >>1;if(Sa.check (mid,a,b,c,d)) Ans=mid,l=mid+1;ElseR=mid-1; } printf ("%d\n", ans); }return 0;}
"BZOJ4556" string (suffix array, Chairman tree)