Jzoj1309 最长二重串
给你一个字符串,要你求出最长的至少出现两次的子串
这个题呢,很明显是SA啦 是SAM的裸题!
帅气简介高大上的SAM出现啦(比难看的SA好到不知道哪里去了)
#include<stdio.h> #include<string.h> #include<algorithm> #define N 400010 using namespace std; char str[N]; int s[N][26],mx[N],f[N],sz[N]; int last=1,cnt=1,n,v[N],r[N],ans=0; inline int extend(char c){ int p=last,np=last=++cnt,q,nq; c-='a'; mx[np]=mx[p]+1; sz[np]=1; for(;p&&!s[p][c];p=f[p]) s[p][c]=np; if(!p) return f[np]=1; q=s[p][c]; if(mx[p]+1==mx[q]) f[np]=q; else { nq=++cnt; mx[nq]=mx[p]+1; f[nq]=f[q]; f[q]=f[np]=nq; memcpy(s[nq],s[q],26<<2); for(;p&&s[p][c]==q;p=f[p]) s[p][c]=nq; } } int main(){ scanf("%d%s",&n,str); for(int i=0;i<n;++i) extend(str[i]); for(int i=1;i<=cnt;++i) ++v[mx[i]]; for(int i=1;i<=n;++i) v[i]+=v[i-1]; for(int i=cnt;i;--i) r[v[mx[i]]--]=i; for(int p,i=cnt;i;--i){ p=r[i]; sz[f[p]]+=sz[p]; if(sz[p]>1) ans=max(ans,mx[p]); } printf("%d\n",ans); }