BZOJ3926 ZJOI2015 广义后缀自动机

https://www.lydsy.com/JudgeOnline/problem.php?id=3926

CLJ老师题解

http://wjmzbmr.com/archives/zjoi-2015-day-1%E9%A2%98%E8%A7%A3/

对于树上的所有叶子节点领出来做Tire

再将所有Tire合并起来

再弄一个广义后缀自动机维护所有子串

ans=Σleni-lenfa[i]

#include<cstdio>
#include<algorithm>
#include<cstring>
#define rep(i,s,t) for(register int i=s;i<=t;++i)
#define _rep(i,s,t) for(register int i=s;i>=t;--i)
#define Rep(i,s,t) for(register int i=s;i<t;++i)
using namespace std;
namespace IO{
    #define gc getchar()
    #define pc(x) putchar(x)
    template<typename T>inline void read(T &x){
        x=0;int f=1;char ch=gc;
        while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=gc;}
        while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=gc;
        x*=f;return;
    }
    template<typename T>inline void write(T x=0){
        T wr[51];wr[0]=0;
        if(x<0)pc('-'),x=-x;
        if(!x)pc(48);
        while(x)wr[++wr[0]]=x%10,x/=10;
        while(wr[0])pc(48+wr[wr[0]--]);
        return;
    }
}
using IO::read;
using IO::write;
const int N=1e6+11;
typedef long long ll;
int t,x,y,tot,n,m;
ll k;
struct SAM{
    int ch[N<<2][20],las,cnt,fa[N<<2],c[N<<2],pos[N<<2];
    ll ans,l[N<<2];
    SAM(){
        las=cnt=1;
    }
    inline int add(int las,int c){
        int np=++cnt,p=las;l[np]=l[p]+1;
        for(;p&&!ch[p][c];p=fa[p])ch[p][c]=np;
        if(!p)fa[np]=1;
        else{
            int q=ch[p][c];
            if(l[p]+1==l[q])
                fa[np]=q;
            else{
                int nq=++cnt;l[nq]=l[p]+1;
                memcpy(ch[nq],ch[q],sizeof ch[q]);
                fa[nq]=fa[q],fa[q]=fa[np]=nq;
                for(;ch[p][c]==q;p=fa[p])ch[p][c]=nq;
            }
        }
        return np;
    }
    inline void solve(){
        _rep(i,cnt,1)
            ans+=l[i]-l[fa[i]];
        printf("%lld\n",ans);
    }
}sam;
int v[N],las[N],to[N],nxt[N],deg[N];
inline void add(int x,int y){
    nxt[++tot]=las[x],las[x]=tot,to[tot]=y,++deg[y];
}
inline void dfs(int x,int fa,int p){
    int T=sam.add(p,v[x]);
    for(register int e=las[x];e;e=nxt[e])
        if(to[e]!=fa)
            dfs(to[e],x,T);
}
int main(){
    read(n),read(m);
    rep(i,1,n)
        read(v[i]);
    rep(i,2,n)
        read(x),read(y),
        add(x,y),add(y,x);
    rep(i,1,n)
        if(deg[i]==1)
            dfs(i,0,1);
    sam.solve();
    return 0;
}
code

 

posted @ 2018-05-04 22:38  Stump  阅读(171)  评论(0编辑  收藏  举报