学习笔记戳这里: 折跃
论文戳这里: 折跃
论文中的例题:
SPOJ NSUBSTR - Substrings
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; inline int read() { int x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } #define MAXN 2500010 int N,a[MAXN],dp[MAXN],st[MAXN],Right[MAXN<<1],id[MAXN<<1]; char s[MAXN]; namespace SAM { int son[MAXN<<1][27],len[MAXN<<1],par[MAXN<<1]; int sz,last,root; inline void Init() {root=sz=last=1;} inline void Extend(int c) { int cur=++sz,p=last; len[cur]=len[p]+1; while (p && !son[p][c]) son[p][c]=cur,p=par[p]; if (!p) par[cur]=root; else { int q=son[p][c]; if (len[p]+1==len[q]) par[cur]=q; else { int nq=++sz; memcpy(son[nq],son[q],sizeof(son[nq])); par[nq]=par[q]; len[nq]=len[p]+1; while (p && son[p][c]==q) son[p][c]=nq,p=par[p]; par[cur]=par[q]=nq; } } last=cur; } inline void Build() {Init(); for (int i=1; i<=N; i++) Extend(a[i]=s[i]-'a'+1);} }using namespace SAM; int main() { scanf("%s",s+1); N=strlen(s+1); SAM::Build(); for (int i=1,now=root; i<=N; i++) now=son[now][a[i]],Right[now]++; for (int i=1; i<=sz; i++) st[len[i]]++; for (int i=1; i<=N; i++) st[i]+=st[i-1]; for (int i=1; i<=sz; i++) id[st[len[i]]--]=i; for (int i=sz; i>=1; i--) Right[par[id[i]]]+=Right[id[i]]; for (int i=1; i<=sz; i++) dp[len[i]]=max(dp[len[i]],Right[i]); for (int i=N; i>=1; i--) dp[i-1]=max(dp[i-1],dp[i]); for (int i=1; i<=N; i++) printf("%d\n",dp[i]); return 0; }