• BZOJ4516 SDOI2016生成魔咒(后缀自动机)


      本质不同子串数量等于所有点的len-parent树上父亲的len的和。可以直接维护。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<map>
    using namespace std;
    #define ll long long
    #define N 200010
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
    	int x=0,f=1;char c=getchar();
    	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    	return x*f;
    }
    int n,fail[N],len[N],cnt=1,last=1;
    ll ans;
    map<int,int> son[N];
    void relink(int x,int y)
    {
    	ans+=len[fail[x]];
    	fail[x]=y;
    	ans-=len[fail[x]];
    }
    void ins(int c)
    {
    	int x=++cnt,p=last;last=x;ans+=len[x]=len[p]+1;
    	while (son[p].find(c)==son[p].end()) son[p][c]=x,p=fail[p];
    	if (!p) relink(x,1);
    	else
    	{
    		int q=son[p][c];
    		if (len[p]+1==len[q]) relink(x,q);
    		else
    		{
    			int y=++cnt;
    			ans+=len[y]=len[p]+1;
    			son[y]=son[q];
    			relink(y,fail[q]);
    			relink(q,y);
    			relink(x,y);
    			while (son[p][c]==q) son[p][c]=y,p=fail[p];
    		}
    	}
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
    	freopen("qwq.in","r",stdin);
    	freopen("qwq.out","w",stdout);
    	const char LL[]="%I64d
    ";
    #else
    	const char LL[]="%lld
    ";
    #endif
    	n=read();
    	for (int i=1;i<=n;i++)
    	{
    		ins(read());
    		printf(LL,ans);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    poj1228 Grandpa's Estate
    poj1113 Wall
    poj2826 An Easy Problem?!
    poj1269 Intersecting Lines
    poj3304 Segments
    BZOJ3832Rally题解
    BZOJ2802Warehouse Store题解
    李超树详解
    BZOJ4241历史研究题解
    洛谷2050 BZOJ2897美食节题解
  • 原文地址:https://www.cnblogs.com/Gloid/p/10810283.html
Copyright © 2020-2023  润新知