P3804 [模板]字尾自動機 題解
阿新 • • 發佈:2022-05-18
拆出來的點貢獻為 \(0\),其他貢獻為 \(1\),在 DAWG 上統計一個字尾和即可。
點選檢視程式碼
const int N=1e6+13,M=26; int n,len[N<<1],nxt[N<<1],ptot=1,lastpos=1,ind[N<<1]; ll cnt[N<<1]; std::array<int,M> son[N<<1],boom; char s[N]; inline int newpos(std::array<int,M> nson,int nlen){return ++ptot,len[ptot]=nlen,swap(son[ptot],nson),ptot;} inline void insert(int c){ int p=lastpos;int u=newpos(boom,len[p]+1);cnt[u]=1; while(p&&!son[p][c]) son[p][c]=u,p=nxt[p]; if(!p) return lastpos=u,nxt[u]=1,void(); int d=son[p][c]; if(len[d]==len[p]+1) nxt[u]=d; else{ int v=newpos(son[d],len[p]+1); nxt[v]=nxt[d],nxt[d]=v,nxt[u]=v; while(p&&son[p][c]==d) son[p][c]=v,p=nxt[p]; } lastpos=u; } int main(){ #ifdef LOCAL freopen("P3804_4.in","r",stdin); #endif read(s+1);n=strlen(s+1); for(int i=1;i<=n;++i) insert(s[i]-'a'); for(int i=2;i<=ptot;++i) ind[nxt[i]]++; std::queue<int> q; for(int i=2;i<=ptot;++i) if(!ind[i]) q.push(i); while(!q.empty()){ int u=q.front();q.pop(); if(nxt[u]==1) continue; cnt[nxt[u]]+=cnt[u]; if(!(--ind[nxt[u]])) q.push(nxt[u]); } ll ans=0; for(int i=2;i<=ptot;++i) if(cnt[i]>1) ans=max(ans,cnt[i]*len[i]); println(ans); return 0; }