bzoj4516

后缀自动机

留个板子

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\n", ans);
    }
    return 0;
}
View Code

 

posted @ 2017-11-15 14:14  19992147  阅读(109)  评论(0编辑  收藏  举报