BZOJ4556 [Tjoi2016&Heoi2016]字符串

来源:互联网 发布:学哪种编程语言好? 编辑:程序博客网 时间:2024/05/16 23:56

恩,我们进行一些瞎YY,首先询问s[a~b]的所有子串与S[c~d]的最长LCP其实相当于询问s[a~b]的所有后缀与s[c~d]的最长LCP与这个子串的长度还有c~d的长度取min

进一步转化设suf[i]表示S的从第i个字符开始的后缀,则其实相当于询问这个

可以把d-c+1提到外面,就变成

这样只需要考虑左面的,考虑若答案为l(l<=d-c+1),则作为答案的后缀不可能取在i>b-l+1的位置,而在a<=i<=b-l+1的范围内,只要LCP(suf[i],suf[c])>=l,那么s[i~b]就是一个与s[c~d]有长度为l的LCP的子串

这样我们可以在<=d-c+1的范围内二分答案,每次只要判断a<=i<=b-mid+1的范围内是否存在LCP(suf[i],suf[c])>=mid即可,这个判断可以先建一颗后缀树,在后缀树上倍增找到suf[c]的最浅的长度>=mid的祖先,然后判断这个祖先的子树内是否有a<=i<=b-mid+1的后缀即可,这个可以用主席树

复杂度 O(m log^2 n)

#include<iostream>#include<cstdlib>#include<cstdio>#include<cstring>#include<cmath>#include<ctime>#include<algorithm>#include<iomanip>#include<vector>#include<stack>#include<queue>#include<map>#include<set>#include<bitset>using namespace std;#define MAXN 200010#define MAXM 4000010#define ll long long#define INF 1000000000#define MOD 1000000007#define eps 1e-8struct vec{int to;int fro;};int fa[MAXN],son[MAXN][26],mx[MAXN];int rt,lst,tot;int n,m;char s[MAXN];int Son[MAXM][2],Siz[MAXM];int Tot;int Rt[MAXN];vec mp[MAXN];int tai[MAXN],cnt;int dfn[MAXN],ndf[MAXN],siz[MAXN],tim;int Fa[MAXN][20];int dep[MAXN];int P[MAXN];vector<int>tp[MAXN];inline void be(int x,int y){mp[++cnt].to=y;mp[cnt].fro=tai[x];tai[x]=cnt;}void ins(int x){int np=++tot,p=lst;mx[np]=mx[p]+1;while(p&&!son[p][x]){son[p][x]=np;p=fa[p];}if(!p){fa[np]=rt;}else{int q=son[p][x];if(mx[q]==mx[p]+1){fa[np]=q;}else{int nq=++tot;mx[nq]=mx[p]+1;memcpy(son[nq],son[q],sizeof(son[q]));fa[nq]=fa[q];fa[np]=fa[q]=nq;while(p&&son[p][x]==q){son[p][x]=nq;p=fa[p];}}}lst=np;}void dfs(int x){int i,j,t,y;dfn[x]=++tim;ndf[tim]=x;siz[x]=1;dep[x]=dep[Fa[x][1]]+1;for(i=tai[x];i;i=mp[i].fro){y=mp[i].to;for(t=x,j=1;t;j++){Fa[y][j]=t;t=Fa[t][j];}dfs(y);siz[x]+=siz[y];}}void change(int &x,int xx,int l,int r,int p){x=++Tot;memcpy(Son[x],Son[xx],sizeof(Son[x]));Siz[x]=Siz[xx]+1;if(l==r){return ;}int mid=l+r>>1;if(p<=mid){change(Son[x][0],Son[xx][0],l,mid,p);}else{change(Son[x][1],Son[xx][1],mid+1,r,p);}}int anc(int x,int y){int i;for(i=19;i;i--){if(mx[Fa[x][i]]>=y){x=Fa[x][i];}}return x;}int ask(int x,int xx,int y,int z,int l,int r){if(y==l&&z==r){return Siz[xx]-Siz[x];}int mid=y+z>>1;if(r<=mid){return ask(Son[x][0],Son[xx][0],y,mid,l,r);}else if(l>mid){return ask(Son[x][1],Son[xx][1],mid+1,z,l,r);}else{return ask(Son[x][0],Son[xx][0],y,mid,l,mid)+ask(Son[x][1],Son[xx][1],mid+1,z,mid+1,r);}}bool OK(int x,int y,int z){return ask(Rt[dfn[x]-1],Rt[dfn[x]+siz[x]-1],1,n,y,z);}int main(){lst=rt=tot=1;int i,j,x,y,xx,yy;scanf("%d%d",&n,&m);scanf("%s",s+1);int p=rt;for(i=n;i;i--){ins(s[i]-'a');p=son[p][s[i]-'a'];P[i]=p;tp[P[i]].push_back(i);}for(i=2;i<=tot;i++){be(fa[i],i);}dfs(1);for(i=1;i<=tim;i++){Rt[i]=Rt[i-1];for(j=0;j<tp[ndf[i]].size();j++){change(Rt[i],Rt[i],1,n,tp[ndf[i]][j]);}}while(m--){scanf("%d%d%d%d",&x,&y,&xx,&yy);int l=1,r=min(yy-xx+1,y-x+1);int ans=0;while(l<=r){int mid=l+r>>1;if(OK(anc(P[xx],mid),x,y-mid+1)){ans=mid;l=mid+1;}else{r=mid-1;}}printf("%d\n",ans);}return 0;}/*8 1ababcabc1 3 6 8*/


0 0
原创粉丝点击