zoukankan      html  css  js  c++  java
  • bzoj3929(sam)

    因为题目中树的特殊性暴力dfs建sam就好了。然后sam有一个有意思的性质是一个点代表的子串个数等于mx[i]-mx[fail[i]],至于为什么,我不会严谨的证明,但想想还是可以的,就是当前串的所有后缀减去前面已经表示过的后缀吗。其实这个个数也可以一个dp跑出来的,只不过这种方法更卓越。

    #include<iostream>
    #include<cmath>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int maxn=200010;
    int ss[maxn],ch[maxn*20][10],fa[maxn*20],dis[maxn*20],cur=1,cnt=1;
    int n,last[maxn],pre[maxn],other[maxn],cc[maxn],du[maxn],C,t;
    int add(int c,int p){
        cur=++cnt;
        dis[cur]=dis[p]+1;
        for(;p&&!ch[p][c];p=fa[p])ch[p][c]=cur;
        if(!p)fa[cur]=1;
        else{
            int q=ch[p][c];
            if(dis[q]==dis[p]+1)fa[cur]=q;
            else{
                int nt=++cnt;dis[nt]=dis[p]+1;
                memcpy(ch[nt],ch[q],sizeof(ch[0]));
                fa[nt]=fa[q];fa[q]=fa[cur]=nt;
                for(;p&&ch[p][c]==q;p=fa[p])ch[p][c]=nt;
            }
        }
        return cur;
    }
    void dfs(int x,int fa,int p){
        int tmp=add(cc[x],p);
        for(int i=last[x];i;i=pre[i]){
            int v=other[i];
            if(v==fa)continue;
            dfs(v,x,tmp);
        }
    }
    void insert(int x,int y){++t;pre[t]=last[x];last[x]=t;other[t]=y;}
    int main(){
        int x,y;
        cin>>n>>C;
        for(int i=1;i<=n;++i)scanf("%d",&cc[i]);
        for(int i=1;i<n;++i){
            scanf("%d%d",&x,&y);
            du[x]++;du[y]++;
            insert(x,y);insert(y,x);
        }
        for(int i=1;i<=n;++i)if(du[i]==1){
            dfs(i,0,1);
        }
        long long ans=0;
        for(int i=1;i<=cnt;++i)
        ans+=dis[i]-dis[fa[i]];
        cout<<ans;
        //system("pause");
        return 0;
    }
  • 相关阅读:
    collections工具类 排序
    API text|lang
    异常处理
    extends继承
    接口
    static修饰符
    多态与find关键词
    Markdown语法
    Hexo | (五)Yilia主题优化
    Hexo | (四)多机同步更新博客
  • 原文地址:https://www.cnblogs.com/dibaotianxing/p/8391091.html
Copyright © 2011-2022 走看看