后缀自动机板子题
一开始把后缀自动机封装了直接ce两发orz
本质不同的子串个数就是所有len[x]-len[fa[x]]的累加和
然后insert一个字符算一次
复杂度:均摊O(n)
/************************************************************** Problem: 4516 User: syh0313 Language: C++ Result: Accepted Time:960 ms Memory:21184 kb ****************************************************************/ #include <iostream> #include <cstdio> #include <cstdlib> #include <map> using namespace std; const int N=400010; long long ans; map< int , int > son[N]; int last,root; int fa[N],len[N],cnt=0; inline void insert( int ch) { int p=last,np=++cnt;last=np;len[np]=len[p]+1; while (p&&!son[p][ch]) son[p][ch]=np,p=fa[p]; if (!p) fa[np]=root; else { int q=son[p][ch]; if (len[q]==len[p]+1) fa[np]=q; else { int nq=++cnt;len[nq]=len[p]+1;son[nq]=son[q]; fa[nq]=fa[q];fa[q]=fa[np]=nq; while (son[p][ch]==q) son[p][ch]=nq,p=fa[p]; } } ans+=( long long )len[np]-len[fa[np]]; } int n,x; int main() { scanf ( "%d" ,&n); last=root=++cnt; for ( int i=1;i<=n;i++) { scanf ( "%d" ,&x); insert(x); printf ( "%lld\n" ,ans);} return 0; } |