BZOJ 4516 [Sdoi2016]生成魔咒 ——后缀自动机

本质不同的字串,考虑SA的做法,比较弱,貌似不会。

好吧,只好用SAM了,由于后缀自动机的状态最简的性质,

所有不同的字串就是∑l[i]-l[fa[i]],

然后后缀自动机是可以在线的,然后维护一下就可以了。

 

#include <map>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
 
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)
#define ll long long
#define maxn 200005
 
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
 
struct Suffix_Automata{
    map<int,int> go[maxn];
    char s[maxn];
    ll ans;
    int l[maxn],fa[maxn],last,cnt;
    void init(){last=cnt=1;}
    void add(int x)
    {
        int p=last,np=last=++cnt; l[np]=l[p]+1;
        for (;p&&!go[p][x];p=fa[p]) go[p][x]=np;
        if (!p) fa[np]=1;
        else
        {
            int q=go[p][x];
            if (l[q]==l[p]+1) fa[np]=q;
            else
            {
                int nq=++cnt;
                l[nq]=l[p]+1;
                go[nq]=go[q];
                fa[nq]=fa[q];
                fa[q]=fa[np]=nq;
                for (;p&&go[p][x]==q;p=fa[p]) go[p][x]=nq;
            }
        }
        ans+=l[last]-l[fa[last]];
    }
    void solve()
    {
        init();
        int n; ans=0;
        n=read();
        F(i,1,n)
        {
            int x;
            x=read();
            add(x);
            printf("%lld\n",ans);
        }
    }
}sam;
int main(){sam.solve();}

  

posted @ 2017-03-01 22:59  SfailSth  阅读(141)  评论(0编辑  收藏  举报