感谢dalaoWJZ的讲解。
我们对于每一个串a[i]相当于在他parent的right集合里找一个出现位置在id-len[x]+len[parent]到id[x]-1区间的
用主席树判存在性即可。
至于我问了很久这个区间为什么不能往前判,原因是你每个节点都代表唯一一个子串,所以我们定性查询就可以啦。
By:大奕哥
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=4e5+10; 4 int rt[N],num,n; 5 char s[N]; 6 struct tree{ 7 int l,r; 8 }t[N*50]; 9 void change(int &x,int l,int r,int p) 10 { 11 if(!x)x=++num; 12 if(l==r)return; 13 int mid=l+r>>1; 14 if(p>mid)change(t[x].r,mid+1,r,p); 15 else change(t[x].l,l,mid,p); 16 } 17 void merge(int &x,int y) 18 { 19 if(!x||!y){x=x+y;return;} 20 ++num;t[num]=t[x];x=num; 21 merge(t[x].l,t[y].l); 22 merge(t[x].r,t[y].r); 23 } 24 bool query(int x,int l,int r,int L,int R) 25 { 26 if(!x)return 0; 27 if(l==L&&r==R)return 1; 28 int mid=l+r>>1; 29 if(mid<L)return query(t[x].r,mid+1,r,L,R); 30 else if(mid>R)return query(t[x].l,l,mid,L,R); 31 else return query(t[x].l,l,mid,L,mid)|query(t[x].r,mid+1,r,mid+1,R); 32 } 33 struct SAM 34 { 35 int cnt,root,last,c[N][26],f[N],dp[N],tt[N],pos[N],r[N],id[N],l[N]; 36 SAM(){cnt=0;last=root=++cnt;} 37 void add(int x,int dd) 38 { 39 int now=last,a=++cnt;last=a;id[a]=dd; 40 l[a]=l[now]+1; 41 for(;now&&!c[now][x];now=f[now])c[now][x]=a; 42 if(!now)f[a]=root; 43 else{ 44 int q=c[now][x]; 45 if(l[q]==l[now]+1)f[a]=q; 46 else{ 47 int b=++cnt;id[b]=dd; 48 l[b]=l[now]+1; 49 f[b]=f[q]; 50 f[a]=f[q]=b; 51 memcpy(c[b],c[q],sizeof(c[q])); 52 for(;now&&c[now][x]==q;now=f[now])c[now][x]=b; 53 } 54 } 55 return; 56 } 57 void sort(){ 58 for(int i=1;i<=cnt;++i)tt[l[i]]++; 59 for(int i=1;i<=n;++i)tt[i]+=tt[i-1]; 60 for(int i=1;i<=cnt;++i)r[tt[l[i]]--]=i; 61 return; 62 } 63 void work() 64 { 65 for(int i=cnt;i>=2;--i) 66 { 67 int x=r[i]; 68 change(rt[x],1,n,id[x]); 69 merge(rt[f[x]],rt[x]); 70 }int ans=1; 71 for(int i=2;i<=cnt;++i) 72 { 73 int x=r[i]; 74 if(f[x]==1){pos[x]=x,dp[x]=1;continue;} 75 if(query(rt[pos[f[x]]],1,n,id[x]-l[x]+l[pos[f[x]]],id[x]-1)) 76 dp[x]=dp[pos[f[x]]]+1,pos[x]=x; 77 else dp[x]=dp[pos[f[x]]],pos[x]=pos[f[x]]; 78 ans=max(ans,dp[x]); 79 } 80 printf("%d ",ans); 81 return; 82 } 83 }A; 84 int main() 85 { 86 scanf("%d%s",&n,s+1); 87 for(int i=1;i<=n;++i)A.add(s[i]-'a',i); 88 A.sort();A.work(); 89 return 0; 90 }