洛谷 P3804 【模板】后缀自动机
来一份模板
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<queue> 5 using namespace std; 6 typedef long long LL; 7 char s[1000100]; 8 int n; 9 LL ans; 10 namespace SAM 11 { 12 int mem,np,root; 13 int len[2000100],par[2000100]; 14 int trans[2000100][26]; 15 int in[2000100],sz[2000100]; 16 void append(int ch) 17 { 18 int p=np;np=++mem;len[np]=len[p]+1; 19 for(;p&&!trans[p][ch];p=par[p]) trans[p][ch]=np; 20 if(!p) par[np]=root; 21 else 22 { 23 int q=trans[p][ch]; 24 if(len[q]==len[p]+1) par[np]=q; 25 else 26 { 27 int nq=++mem;par[nq]=par[q];par[q]=par[np]=nq; 28 memcpy(trans[nq],trans[q],sizeof(trans[nq]));len[nq]=len[p]+1; 29 for(;p&&trans[p][ch]==q;p=par[p]) trans[p][ch]=nq; 30 } 31 } 32 sz[np]=1; 33 } 34 void build() 35 { 36 np=root=++mem; 37 for(int i=1;i<=n;i++) append(s[i]-'a'); 38 } 39 queue<int> q; 40 void work() 41 { 42 int i,t; 43 for(i=1;i<=mem;i++) ++in[par[i]]; 44 for(i=1;i<=mem;i++) 45 if(!in[i]) 46 q.push(i); 47 while(!q.empty()) 48 { 49 t=q.front();q.pop(); 50 if(sz[t]>1) ans=max(ans,LL(sz[t])*len[t]); 51 if(par[t]) 52 { 53 sz[par[t]]+=sz[t]; 54 --in[par[t]]; 55 if(!in[par[t]]) q.push(par[t]); 56 } 57 } 58 } 59 } 60 61 int main() 62 { 63 scanf("%s",s+1);n=strlen(s+1); 64 SAM::build();SAM::work(); 65 printf("%lld",ans); 66 return 0; 67 }
还有后缀数组强行A此题
1 #pragma GCC optimize("Ofast") 2 #pragma GCC target("sse3","sse2","sse") 3 #pragma GCC target("avx","sse4","sse4.1","sse4.2","ssse3") 4 #pragma GCC target("f16c") 5 #pragma GCC optimize("inline","fast-math","unroll-loops","no-stack-protector") 6 #pragma GCC diagnostic error "-fwhole-program" 7 #pragma GCC diagnostic error "-fcse-skip-blocks" 8 #pragma GCC diagnostic error "-funsafe-loop-optimizations" 9 #pragma GCC diagnostic error "-std=c++14" 10 #include<cstdio> 11 #include<algorithm> 12 #include<cstring> 13 #include<map> 14 using namespace std; 15 char s[1000100]; 16 int n; 17 namespace SA 18 { 19 int sa[1000100],t1[1000100],t2[1000100],m='z',cnt[1000100],p; 20 int *x=t1,*y=t2,*rk=t1,*height=t2; 21 template<typename T> 22 T get(int pos,T *a) 23 { 24 return pos<=n?a[pos]:0; 25 } 26 void build() 27 { 28 int i,k;int *it,*ed; 29 for(i=1;i<=n;++i) ++cnt[x[i]=s[i]]; 30 for(it=cnt+1,ed=cnt+m+1;it!=ed;++it) *it+=*(it-1); 31 for(i=n;i>=1;--i) sa[cnt[x[i]]--]=i; 32 for(k=1;k<=n;k<<=1) 33 { 34 p=0; 35 for(i=n-k+1;i<=n;++i) y[++p]=i; 36 for(i=1;i<=n;++i) if(sa[i]>k) y[++p]=sa[i]-k; 37 for(it=cnt+1,ed=cnt+m+1;it!=ed;++it) *it=0; 38 for(i=1;i<=n;++i) cnt[x[y[i]]]++; 39 for(it=cnt+1,ed=cnt+m+1;it!=ed;++it) *it+=*(it-1); 40 for(i=n;i>=1;--i) sa[cnt[x[y[i]]]--]=y[i]; 41 swap(x,y);p=0; 42 for(i=1;i<=n;++i) 43 x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&get(sa[i]+k,y)==get(sa[i-1]+k,y) 44 ?p:++p; 45 if(p>=n) break; 46 m=p; 47 } 48 for(i=1;i<=n;++i) rk[sa[i]]=i; 49 for(i=1,k=1;i<=n;++i) 50 { 51 if(k) k--; 52 if(rk[i]) 53 while(get(sa[rk[i]-1]+k,s)==get(i+k,s)) k++; 54 height[rk[i]]=k; 55 } 56 } 57 } 58 int sz[1000100],fa[1000100]; 59 int find(int x) {return x==fa[x]?x:fa[x]=find(fa[x]);} 60 typedef pair<int,int> P; 61 typedef long long LL; 62 P tmp[1000100]; 63 LL ans; 64 bool cmp(const P& a,const P& b) 65 { 66 return a>b; 67 } 68 int main() 69 { 70 int i,d,t,fx,fy; 71 scanf("%s",s+1);n=strlen(s+1);SA::build(); 72 for(i=1;i<=n;i++) fa[i]=i,sz[i]=1; 73 for(i=2;i<=n;i++) tmp[i]=P(SA::height[i],i); 74 sort(tmp+2,tmp+n+1,cmp); 75 for(i=2;i<=n;i++) 76 { 77 d=tmp[i].first;t=tmp[i].second; 78 fx=find(t-1);fy=find(t); 79 sz[fy]+=sz[fx];fa[fx]=fy; 80 ans=max(ans,LL(sz[fy])*d); 81 } 82 printf("%lld",ans); 83 return 0; 84 }
以下是作死用map之后T掉的程序
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<map> 5 #include<queue> 6 using namespace std; 7 typedef long long LL; 8 char s[1000100]; 9 int n; 10 LL ans; 11 namespace SAM 12 { 13 int mem,np,root; 14 int len[2000100],par[2000100]; 15 map<int,int> trans[2000100]; 16 int in[2000100],sz[2000100]; 17 void append(int ch) 18 { 19 int p=np;np=++mem;len[np]=len[p]+1; 20 for(;p&&!trans[p].count(ch);p=par[p]) trans[p][ch]=np; 21 if(!p) par[np]=root; 22 else 23 { 24 int q=trans[p][ch]; 25 if(len[q]==len[p]+1) par[np]=q; 26 else 27 { 28 int nq=++mem;par[nq]=par[q];par[q]=par[np]=nq; 29 trans[nq]=trans[q];len[nq]=len[p]+1; 30 for(;p&&trans[p].count(ch)&&trans[p][ch]==q;p=par[p]) trans[p][ch]=nq; 31 } 32 } 33 sz[np]=1; 34 } 35 void build() 36 { 37 np=root=++mem; 38 for(int i=1;i<=n;i++) append(s[i]-'a'); 39 } 40 queue<int> q; 41 void work() 42 { 43 int i,t; 44 for(i=1;i<=mem;i++) ++in[par[i]]; 45 for(i=1;i<=mem;i++) 46 if(!in[i]) 47 q.push(i); 48 while(!q.empty()) 49 { 50 t=q.front();q.pop(); 51 if(sz[t]>1) ans=max(ans,LL(sz[t])*len[t]); 52 if(par[t]) 53 { 54 sz[par[t]]+=sz[t]; 55 --in[par[t]]; 56 if(!in[par[t]]) q.push(par[t]); 57 } 58 } 59 } 60 } 61 62 int main() 63 { 64 scanf("%s",s+1);n=strlen(s+1); 65 SAM::build();SAM::work(); 66 printf("%lld",ans); 67 return 0; 68 }