码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 3926 Zjoi2015 诸神眷顾的幻想乡 后缀自动机

时间:2015-04-04 09:22:58      阅读:126      评论:0      收藏:0      [点我收藏+]

标签:bzoj   bzoj3926   后缀自动机   

题目大意:给定一棵树,每个节点有一个字符,求从一个节点出发沿最短路径走到另一个节点所构成的字符串一共有多少种

此生无悔入东方,来世愿生幻想乡

题目戳这里

注意一句话:太阳花田的结构比较特殊,只与一个空地相邻的空地的数量不超过20个

有奖问答:↑你看到这句话的第一反应是啥?

1.度数<=20

2.叶节点数<=20

仔细看几遍就能找到答案~

[捂脸熊]陈老师真是语文高手。。。。

叶节点数<=20还做啥了。。。

直接从每个叶节点DFS一遍,然后构建广义后缀自动机,最终答案就是每个节点的深度-parent节点的深度之和

还有一种后缀数组的做法是DFS20遍构建一棵Trie树,然后将Trie树建成后缀数组(OTZ),然后一样搞就是了

OTZ

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 100100
using namespace std;
struct abcd{
    int to,next;
}table[M<<1];
int head[M],tot;
int n,c,a[M];
long long ans;
int degree[M];
void Add(int x,int y)
{
    table[++tot].to=y;
    table[tot].next=head[x];
    head[x]=tot;
}
namespace Suffix_Automaton{
    struct Sam{
        Sam *son[10],*parent;
        int max_dpt;
        bool v;
        void* operator new (size_t,int _)
        {
            #define L (1<<15)
            static Sam *mempool,*C;
            if(C==mempool)
                mempool=(C=new Sam[L])+L;
            C->max_dpt=_;
            C->parent=0x0;
            C->v=false;
            memset(C->son,0,sizeof C->son);
            return C++;
        }
    }*root=new (0)Sam;
    Sam* Extend(Sam *p,int x)
    {
        if(p->son[x]&&p->son[x]->max_dpt==p->max_dpt+1)
            return p->son[x];
        Sam *np=new (p->max_dpt+1)Sam;
        while(p&&!p->son[x])
            p->son[x]=np,p=p->parent;
        if(!p)
            np->parent=root;
        else
        {
            Sam *q=p->son[x];
            if(p->max_dpt+1==q->max_dpt)
                np->parent=q;
            else
            {
                Sam *nq=new (p->max_dpt+1)Sam;
                nq->parent=q->parent;
                memcpy(nq->son,q->son,sizeof nq->son);
                q->parent=nq;np->parent=nq;
                for(;p&&p->son[x]==q;p=p->parent)
                    p->son[x]=nq;
            }
        }
        return np;
    }
}
using namespace Suffix_Automaton;
Sam *node[M];
void DFS(int x,int from)
{
    int i;
    node[x]=Extend(node[from],a[x]);
    for(i=head[x];i;i=table[i].next)
        if(table[i].to!=from)
            DFS(table[i].to,x);
}
void BFS()
{
    static Sam *q[4004004];
    int i,r=0,h=0;
    q[++r]=root;
    while(r!=h)
    {
        Sam *p=q[++h];
        if(p!=root)
            ans+=p->max_dpt-p->parent->max_dpt;
        for(i=0;i<c;i++)
            if(p->son[i]&&!p->son[i]->v)
                p->son[i]->v=true,q[++r]=p->son[i];
    }
}
int main()
{
    int i,x,y;
    cin>>n>>c;
    for(i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(i=1;i<n;i++)
    {
        scanf("%d%d",&x,&y);
        Add(x,y);Add(y,x);
        degree[x]++;
        degree[y]++;
    }
    node[0]=root;
    for(i=1;i<=n;i++)
        if(degree[i]==1)
            DFS(i,0);
    BFS();
    cout<<ans<<endl;
    return 0;
}


BZOJ 3926 Zjoi2015 诸神眷顾的幻想乡 后缀自动机

标签:bzoj   bzoj3926   后缀自动机   

原文地址:http://blog.csdn.net/popoqqq/article/details/44858451

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!