The topic is to give a string, every time a range [A, b] all of the substrings and another interval [c,d] LCP maximum value, first of all to find the suffix array, the maximum value of LCP is definitely RANK[C] precursor and successor, but for this problem will be problems, is the subject of the interval limit.
For example:
5 1
Aaaab
1 2 3 5
For this example, if the precursor to the AAB is Aaab, then the answer is 1 because of the interval, but if we find the Aaaab, the answer will become 2. Then there was a mistake. Think about what you can do to get rid of this effect?
We can have two minutes, first of all, for [a A, a] this interval we only consider the first half of the interval [A,mid] We use the above method to find a precursor and subsequent methods to find out an answer, if the answer is greater than mid we have to consider the mid-range, and then consider the mid-range. (The interval here refers to the interval where the left end of the substring is located)
Why is that right? In the category discussion, if the answer is greater than mid, then it is not possible to consider the interval after mid because it is clear that the interval to B after mid is less than mid and the answer is not optimal. If the answer is less than mid, we will not consider the interval before mid, because the answer is less than mid, obviously it cannot be due to the interval limit, because we only consider the first half of the interval, it must be at the end of the length is greater than or equal to the mid, so we back two points, Because with the expansion of the interval we find the precursor and the successor will certainly become closer to Rank[c], then the answer may be better, and we will not go forward to judge the answer, so the next two points. So the correctness of the two points is ok. (In fact, this nature is very bad think, I was also a half-day, but the big game brother with a violent crush off the mark, Bzoj on Rank1 ... Details can be seen blog http://www.cnblogs.com/nbwzyzngyl/p/8215412.html purely fluke ... )
Then we can use the Chairman tree to do the precursor and follow, this problem solved. --by Vane
#include <bits/stdc++.h>using namespacestd;Const intn=100010;Const intm=4000005;intn,m,a[n],tax[n],tp[n],height[n],st[n][ -],log[n];intsa[n],rank[n],sum[m],ls[m],rs[m],siz,root[n],mm;CharS[n];voidRsort () { for(intI=1; i<=m;++i) tax[i]=0; for(intI=1; i<=n;++i) tax[rank[tp[i]]]++; for(intI=1; i<=m;++i) tax[i]+=tax[i-1]; for(intI=n;i;--i) sa[tax[rank[tp[i]]]--]=tp[i];}BOOLcmpint*f,intXintYintW) {returnMax (x, y) +w<=n&&f[x]==f[y]&&f[x+w]==f[y+W];}voidsuffix () {m=127; for(intI=1; i<=n;++i) tp[i]=i; for(intI=1; i<=n;++i) rank[i]=A[i]; Rsort (); for(intw=1, p;w<n;w+=W) {p=0; for(inti=n-w+1; i<=n;++i) tp[++p]=i; for(intI=1; i<=n;++i)if(sa[i]>w) tp[++p]=sa[i]-W; Rsort (); swap (RANK,TP); rank[sa[1]]=p=1; for(intI=2; i<=n;++i) rank[sa[i]]=cmp (tp,sa[i],sa[i-1],W)? p:++p; M=p;if(p>=n) Break; } intj,k=0; for(intI=1; i<=n;height[rank[i++]]=k) for(k=k?k-1:0, j=sa[rank[i]-1];a[j+k]==a[i+k];++k); memset (St,127,sizeofSt); for(intI=1; i<=n;++i) st[i][0]=Height[i]; for(intj=1; j<= -;++j) for(intI=1; i+ (1<<J)-1<=n;++i) st[i][j]=min (st[i][j-1],st[i+ (1<<j-1)][j-1]); for(intI=2, j=0; i<=n;++i) {if(i== (1<<j+1)) ++J; Log[i]=J; }}intLcpintXinty) { if(x>y) Swap (x, y); intlen=log[y-x+1]; intRet=min (st[x][len],st[y-(1<<len) +1][len]); returnret;}voidInsertintLintRintXint&y,intz) {y=++siz; Sum[y]=sum[x]+1; Ls[y]=ls[x];rs[y]=Rs[x]; if(L==R)return; intMid=l+r>>1; if(z<=mid) Insert (L,MID,LS[X],LS[Y],Z); ElseInsert (mid+1, r,rs[x],rs[y],z);}intQuery_sum (intLintRintXintYintLeintRI) { if(Le>ri)return 0; if(L==le&&r==ri)returnsum[y]-Sum[x]; intMid=l+r>>1; if(Ri<=mid)returnquery_sum (L,mid,ls[x],ls[y],le,ri); if(Le>mid)returnQuery_sum (mid+1, R,rs[x],rs[y],le,ri); returnQuery_sum (L,mid,ls[x],ls[y],le,mid) +query_sum (mid+1, r,rs[x],rs[y],mid+1, RI);}intQuery_pos (intLintRintXintYintp) { if(L==R)returnl; intMid=l+r>>1; if(sum[ls[y]]-sum[ls[x]]>=p)returnQuery_pos (l,mid,ls[x],ls[y],p); returnQuery_pos (mid+1, r,rs[x],rs[y],p-sum[ls[y]]+Sum[ls[x]]);}intMain () {//freopen ("str.in","R", stdin); Freopen ("Str.out","W", stdout); scanf ("%d%d",&n,&mm); scanf ("%s", s+1); for(intI=1; i<=n;++i) a[i]=S[i]; Suffix (); inta,b,c,d,x,pre,sub; for(intI=1; i<=n;++i) Insert (1, n,root[i-1],root[i],rank[i]); while(mm--) {scanf ("%d%d%d%d",&a,&b,&c,&d); intL=0, r=b-a+1, maxn=0, Mid; BOOLflag=0; while(l<=r) {Mid=l+r>>1; X=query_sum (1, n,root[a-1],root[b-mid],1, rank[c]-1); Pre=x?query_pos (1, n,root[a-1],ROOT[B-MID],X):-1; X=query_sum (1, n,root[a-1],root[b-mid],1, Rank[c]); Sub=query_pos (1, n,root[a-1],root[b-mid],1+x); if(x==sum[root[b-mid]]-sum[root[a-1]]) sub=-1; intans=0; if(pre!=-1) { intO=min (LCP (pre+1, Rank[c]), b-sa[pre]+1); Ans=max (Ans,min (o,d-c+1)); } if(sub!=-1) { intO=min (LCP (rank[c]+1, sub), b-sa[sub]+1); Ans=max (Ans,min (o,d-c+1)); } if(c>=a&&c<=b) Ans=max (Ans,min (d,b)-c+1); MAXN=Max (Maxn,ans); if(Ans>=mid) l=mid+1; ElseR=mid; if(flag) Break; if(l==r) flag=1; } printf ("%d\n", MAXN); }}
bzoj4556: [tjoi2016&heoi2016] string (suffix array plus chairman tree)