Description
(我并不想告诉你题目名字是什么鬼)
有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n].
现在有若干组询问,对于每一个询问,我们给出若干个后缀(以其在S中出现的起始位置来表示),求这些后缀两两之间的LCP(LongestCommonPrefix)的长度之和.一对后缀之间的LCP长度仅统计一遍.
Input
第一行两个正整数n,m,分别表示S的长度以及询问的次数.
接下来一行有一个字符串S.
接下来有m组询问,对于每一组询问,均按照以下格式在一行内给出:
首先是一个整数t,表示共有多少个后缀.接下来t个整数分别表示t个后缀在字符串S中的出现位置.
Output
对于每一组询问,输出一行一个整数,表示该组询问的答案.由于答案可能很大,仅需要输出这个答案对于23333333333333333(一个巨大的质数)取模的余数.
建出后缀树,询问相当于后缀树上一些点间两两的lca的深度之和,建出虚树然后树形dp求解
#include<cstdio> #include<cstring> #include<algorithm> typedef long long i64; const int N=1e6+7; char s[N]; int nx[N][26],l[N],fa[N],pp=1,pv=1; int n,m,pos[N]; int e0[N],es[N],enx[N],ep=2,sz[N],son[N],dep[N],top[N],id[N][2],idp=0,ss[N],sp=0; int ed[N],tk=0; char buf[50000000],*ptr=buf-1; int _(){ int x=0; while(*ptr<48)++ptr; while(*ptr>47)x=x*10+*ptr++-48; return x; } void _(char*s){ while(*ptr<33)++ptr; while(*ptr>32)*s++=*ptr++; *ptr=0; } int ins(int x){ int p=pv,np=++pp; l[np]=l[p]+1; while(p&&!nx[p][x])nx[p][x]=np,p=fa[p]; if(!p)fa[np]=1; else{ int q=nx[p][x]; if(l[q]==l[p]+1)fa[np]=q; else{ int nq=++pp; l[nq]=l[p]+1; memcpy(nx[nq],nx[q],sizeof(nx[0])); fa[nq]=fa[q]; fa[q]=fa[np]=nq; while(p&&nx[p][x]==q)nx[p][x]=nq,p=fa[p]; } } return pv=np; } void push(int w){ ss[++sp]=w; id[w][0]=++idp; dep[w]=dep[fa[w]]+1; } void hld_pre(){ for(int i=1;i<=pp;++i){ es[ep]=i;enx[ep]=e0[fa[i]];e0[fa[i]]=ep++; sz[i]=1; } push(1); while(sp){ int w=ss[sp],&e=e0[w]; if(!e){ int f=fa[w]; sz[f]+=sz[w]; if(w[sz]>f[son][sz])f[son]=w; id[w][1]=idp; --sp; continue; } int u=es[e]; e=enx[e]; push(u); } for(int i=1;i<=pp;++i)if(i[fa][son]!=i){ for(int w=i;w;w=w[son])w[top]=i; } } int lca(int x,int y){ int a=top[x],b=top[y]; while(a!=b){ if(dep[a]>dep[b])x=fa[a],a=top[x]; else y=fa[b],b=top[y]; } return dep[x]<dep[y]?x:y; } bool cmp(int a,int b){ return id[a][0]<id[b][0]; } int cs[N],cp,tp[N],_f[N]; void cal(){ i64 ans=0; int p=0; _f[ss[++sp]=cs[p++]]=0; while(sp){ int w=ss[sp]; if(p<cp&&id[cs[p]][0]<=id[w][1])_f[ss[++sp]=cs[p++]]=w; else{ --sp; int f=_f[w]; if(f>1){ ans+=i64(l[f])*tp[f]*tp[w]; tp[f]+=tp[w]; } } } printf("%lld\n",ans); } int main(){ fread(buf,1,sizeof(buf),stdin)[buf]=0; n=_();m=_(); _(s+1); for(int i=n;i;--i)pos[i]=ins(s[i]-'a'); hld_pre(); for(int c;m;--m){ c=_(); cp=0; ++tk; for(int i=0,x;i<c;++i){ x=pos[_()]; if(ed[x]!=tk)ed[cs[cp++]=x]=tk,tp[x]=1; } std::sort(cs,cs+cp,cmp); c=cp; for(int i=0,pv=1;i<c;++i){ int x=lca(cs[i],pv); pv=cs[i]; if(ed[x]!=tk)ed[cs[cp++]=x]=tk,tp[x]=0; } std::sort(cs,cs+cp,cmp); cal(); } return 0; }