【文文殿下】[51nod1469] 淋漓盡致子串
阿新 • • 發佈:2018-11-22
SAM的經典應用
一個狀態的SIze==1絕對不合法。
一個狀態在parent樹上有一個Size>1的後繼絕對不合法(前面可以再補字元)
一個狀態可以轉移到Size>1的節點絕對不合法,因為可以在後面補字元。
#include<cstdio> #include<cstring> #include<map> typedef long long ll; const int maxn = 2e5+20; int par[maxn],mx[maxn],tr[maxn][26],Right[maxn],c[maxn],id[maxn]; char A[maxn>>1]; int tot=0; int cnt = 1,last = 1; ll ans = 0; void extend(int x) { int np = ++cnt,p = last; Right[np]=1; mx[np]=mx[p]+1; last=np; while(p&&!tr[p][x]) tr[p][x]=np,p=par[p]; if(!p) par[np]=1; else { int q = tr[p][x]; if(mx[q]==mx[p]+1) { par[np]=q; } else { int nq = ++cnt; mx[nq]=mx[p]+1; memcpy(tr[nq],tr[q],sizeof tr[nq]); par[nq]=par[q]; par[q]=par[np]=nq; while(p&&tr[p][x]==q) tr[p][x]=nq,p=par[p]; } } return; } int n,k,t; inline void topsort() { for(int i = 1;i<=cnt;++i) ++c[mx[i]]; for(int i = 1;i<=n;++i) c[i]+=c[i-1]; for(int i = 1;i<=cnt;++i) id[c[mx[i]]--]=i; for(int i = cnt;i;--i) Right[par[id[i]]]+=Right[id[i]]; return; } bool vis[maxn]; int main() { scanf("%s",A+1); n = strlen(A+1); for(int i = 1;i<=n;++i) extend(A[i]-'a'); topsort();Right[0]=0; for(int i =cnt;i;--i) { if(Right[id[i]]>1||vis[id[i]]) vis[par[id[i]]]=1; } for(int i = 1;i<=cnt;++i) if(Right[i]<=1) vis[i]=1; for(int i = 1;i<=cnt;++i) for(int j = 0;j<26;++j) if(Right[tr[i][j]]>1) vis[i]=1; for(int i = 2;i<=cnt;++i) if(!vis[i]) ++ans; printf("%lld\n",ans); return 0; }