[luogu4482]Border的四种求法
建立SAM的parent树,记$len_{i}$为节点$i$的长度$,pos_{i}$为$s[1,i]$对应的节点
此时,$s[l,i]$为$s[l,r]$的border$\iff i\in [l,r)\and len_{lca(pos_{i},pos_{r})}\ge i-l+1$
思路:倒序枚举$i\in [1,n]$,更新$s[l,i]$为border的询问(并删除)、加入$r=i$的询问
考虑树剖,记$S_{i}$为$pos_{i}$到根路径上所有重链顶端的父亲,则$lca(pos_{i},pos_{r})\in S_{i}\cup S_{r}$
若$\in S_{i}$,则加入询问时在$pos_{i}$处加入$l$,更新询问时枚举$x\in S_{r}$并子树查询$\ge i-len_{x}+1$
若$\in S_{r}$,则加入询问时枚举$x\in S_{i}$并在$x$处加入$len_{x}+l$,更新询问时链查询$\ge i+1$
用线段树+set(仅叶子处)维护,查询时可以与删除均摊(需加入$\max$的剪枝)
时间复杂度为$o(n\log^{2}n+m\log^{2}n)$,可以通过
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 400005 4 #define L (k<<1) 5 #define R (L+1) 6 #define mid (l+r>>1) 7 int n,V,q,lst,l[N],r[N],nex[N],len[N],ch[N][26]; 8 int pos[N],fa[N],sz[N],son[N],dfn[N],top[N],ans[N]; 9 char s[N];vector<int>e[N],va[N],vd[N]; 10 void add_c(int c){ 11 int p=lst,np=lst=++V; 12 len[np]=len[p]+1; 13 while ((p)&&(!ch[p][c]))ch[p][c]=np,p=nex[p]; 14 if (!p)nex[np]=1; 15 else{ 16 int q=ch[p][c]; 17 if (len[q]==len[p]+1)nex[np]=q; 18 else{ 19 int nq=++V; 20 len[nq]=len[p]+1; 21 nex[nq]=nex[q],nex[np]=nex[q]=nq; 22 memcpy(ch[nq],ch[q],sizeof(ch[q])); 23 while ((p)&&(ch[p][c]==q))ch[p][c]=nq,p=nex[p]; 24 } 25 } 26 } 27 void dfs1(int k,int f){ 28 fa[k]=f,sz[k]=1; 29 for(int i:e[k]){ 30 dfs1(i,k),sz[k]+=sz[i]; 31 if (sz[son[k]]<sz[i])son[k]=i; 32 } 33 } 34 void dfs2(int k,int t){ 35 dfn[k]=++dfn[0],top[k]=t; 36 if (son[k])dfs2(son[k],t); 37 for(int i:e[k]) 38 if (i!=son[k])dfs2(i,i); 39 } 40 void del(int id); 41 struct{ 42 int f[N<<2];set<pair<int,int> >S[N]; 43 void update(int k,int l,int r,int x,int y,int id,int p){ 44 if (l==r){ 45 if (p)S[l].erase(make_pair(y,id)); 46 else S[l].insert(make_pair(y,id)); 47 f[k]=(S[l].empty() ? -n : (*--S[l].end()).first); 48 return; 49 } 50 if (x<=mid)update(L,l,mid,x,y,id,p); 51 else update(R,mid+1,r,x,y,id,p); 52 f[k]=max(f[L],f[R]); 53 } 54 void query(int k,int l,int r,int x,int y,int z,int Id){ 55 if ((l>y)||(x>r)||(f[k]<z))return; 56 if (l==r){ 57 while ((!S[l].empty())&&((*--S[l].end()).first>=z)){ 58 int id=(*--S[l].end()).second; 59 del(id),ans[id]=Id; 60 } 61 f[k]=(S[l].empty() ? -n : (*--S[l].end()).first); 62 return; 63 } 64 query(L,l,mid,x,y,z,Id),query(R,mid+1,r,x,y,z,Id); 65 f[k]=max(f[L],f[R]); 66 } 67 }T1,T2; 68 void query(int Id){ 69 int k=pos[Id]; 70 while (k){ 71 T1.query(1,1,V,dfn[k],dfn[k]+sz[k]-1,Id-len[k]+1,Id); 72 T2.query(1,1,V,dfn[top[k]],dfn[k],Id+1,Id); 73 k=fa[top[k]]; 74 } 75 } 76 void add(int id){ 77 int k=pos[r[id]]; 78 T1.update(1,1,V,dfn[k],l[id],id,0); 79 while (k){ 80 T2.update(1,1,V,dfn[k],len[k]+l[id],id,0); 81 k=fa[top[k]]; 82 } 83 } 84 void del(int id){ 85 if (ans[id]!=l[id]-1)return; 86 int k=pos[r[id]]; 87 T1.update(1,1,V,dfn[k],l[id],id,1); 88 while (k){ 89 T2.update(1,1,V,dfn[k],len[k]+l[id],id,1); 90 k=fa[top[k]]; 91 } 92 } 93 int main(){ 94 scanf("%s%d",s+1,&q); 95 n=strlen(s+1),V=lst=1; 96 for(int i=1;i<=n;i++)add_c(s[i]-'a'),pos[i]=lst; 97 for(int i=2;i<=V;i++)e[nex[i]].push_back(i); 98 dfs1(1,0),dfs2(1,1); 99 for(int i=1;i<=q;i++){ 100 scanf("%d%d",&l[i],&r[i]),ans[i]=l[i]-1; 101 va[r[i]].push_back(i),vd[l[i]].push_back(i); 102 } 103 for(int i=n;i;i--){ 104 query(i); 105 for(int j:va[i])add(j); 106 for(int j:vd[i])del(j); 107 } 108 for(int i=1;i<=q;i++)printf("%d\n",ans[i]-l[i]+1); 109 return 0; 110 }