后缀自动机
留个板子
upd:大概懂了 每次新加入的npRight集合肯定只有最后一个位置,那么求所有长得不一样的子串贡献就是Max-Min+1,因为Right集合只有这一个位置,所以这Max-Min+1个子串只出现在最后一个位置。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N = 2e5 + 5; int n; ll ans; namespace SAM { int root, sz, last; struct node { int par, val; map<int, int> ch; } t[N]; int nw(int x) { t[++sz].val = x; return sz; } void iniSAM() { sz = 0; root = last = nw(0); } void extend(int c) { int p = last, np = nw(t[p].val + 1); while(p && !t[p].ch[c]) t[p].ch[c] = np, p = t[p].par; if(!p) t[np].par = root; else { int q = t[p].ch[c]; if(t[q].val == t[p].val + 1) t[np].par = q; else { int nq = nw(t[p].val + 1); t[nq].ch = t[q].ch; t[nq].par = t[q].par; t[q].par = t[np].par = nq; while(p && t[p].ch[c] == q) t[p].ch[c] = nq, p = t[p].par; } } ans += t[np].val - t[t[np].par].val; last = np; } } using namespace SAM; int main() { scanf("%d", &n); iniSAM(); for(int i = 1; i <= n; ++i) { int x; scanf("%d", &x); extend(x); printf("%lld ", ans); } return 0; }