[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 }
View Code

 

posted @ 2022-08-11 20:29  PYWBKTDA  阅读(99)  评论(0编辑  收藏  举报