zoukankan      html  css  js  c++  java
  • bzoj3926: [Zjoi2015]诸神眷顾的幻想乡(广义SAM)

    3926: [Zjoi2015]诸神眷顾的幻想乡

    题目:传送门 

    简要题意:给出一棵树,每个点有编号和权值,问任意两个节点直接的路径上所有权值按顺序连起来形成的数列不同的个数(A到B和B到A是不一样的)


    题解:

       一道广义SAM的入门题目:和之前的生成魔咒差不多,主要在于对SAM的构造。

       一开始想dfs把每条链插入,很显然发现是错的,不知道根而且会漏情况。

       注意到题目的一个提示:叶子节点不超过20个

       那么考虑每次把这些叶子节点当成根,然后建广义SAM,bfs直接搞,每次记得把last重置为root

       然后直接更新ans啊:ans+=ch[i].dep-ch[ch[i].fail].dep(记得long long)

        PS:状态数:20*100000*2

        


    代码:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<cstdlib>
     4 #include<cmath>
     5 #include<algorithm>
     6 using namespace std;
     7 typedef long long LL;
     8 struct SAM
     9 {
    10     int son[15],fail,dep;
    11     SAM(){memset(son,0,sizeof(son));fail=dep=0;}
    12 }ch[4100000];int root,cnt,la;
    13 int a[110000],ru[110000],head,tail;
    14 int add(int k)
    15 {
    16     int x=a[k];
    17     int p=la,np=++cnt;ch[np].dep=ch[p].dep+1;
    18     while(p && ch[p].son[x]==0)ch[p].son[x]=np,p=ch[p].fail;
    19     if(p==0)ch[np].fail=root;
    20     else
    21     {
    22         int q=ch[p].son[x];
    23         if(ch[q].dep==ch[p].dep+1)ch[np].fail=q;
    24         else
    25         {
    26             int nq=++cnt;ch[nq]=ch[q];
    27             ch[nq].dep=ch[p].dep+1;
    28             ch[np].fail=ch[q].fail=nq;
    29             while(p && ch[p].son[x]==q)ch[p].son[x]=nq,p=ch[p].fail;
    30         }
    31     }
    32     return np;
    33 }
    34 int n,c;
    35 struct trnode
    36 {
    37     int x,y,next;
    38 }tr[210000];int len,last[110000];
    39 void ins(int x,int y)
    40 {
    41     len++;tr[len].x=x;tr[len].y=y;
    42     tr[len].next=last[x];last[x]=len;
    43 }
    44 struct node
    45 {
    46     int x,w;
    47 }list[210000];bool v[110000];
    48 void bt(int st)
    49 {
    50     la=root;memset(v,false,sizeof(v));v[st]=true;
    51     node s;s.x=st;s.w=add(st);
    52     list[1]=s;head=1;tail=2;
    53     while(head!=tail)
    54     {
    55         s=list[head];int x=s.x;
    56         for(int k=last[x];k;k=tr[k].next)
    57         {
    58             int y=tr[k].y;
    59             if(v[y]==false)
    60             {
    61                 v[y]=true;
    62                 node t;t.x=y;
    63                 la=s.w;t.w=add(y);
    64                 list[tail++]=t;
    65             }
    66         }
    67         head++;//v[x]=false;
    68     }
    69 }
    70 int main()
    71 {
    72     cnt=0;root=la=++cnt;scanf("%d%d",&n,&c);len=0;memset(last,0,sizeof(last));
    73     for(int i=1;i<=n;i++)scanf("%d",&a[i]);memset(ru,0,sizeof(ru));
    74     for(int i=1;i<n;i++){int x,y;scanf("%d%d",&x,&y);ins(x,y);ins(y,x);ru[x]++;ru[y]++;}
    75     for(int i=1;i<=n;i++)if(ru[i]==1)bt(i);
    76     LL ans=0;for(int i=1;i<=cnt;i++)ans+=(LL(ch[i].dep-ch[ch[i].fail].dep));
    77     printf("%lld
    ",ans);
    78     return 0;
    79 }
  • 相关阅读:
    如何快速查看archlinux pacman 软件记录?
    如何快速判断检查主机ip端口是否存活?
    如何在不清楚有哪些tag的情况下拉取docker镜像?
    如何使用docker版Openresty测试框架Test::Nginx进行测试?
    .net mvc4 使用 System.Web.Optimization 对javascript和style的引入、代码合并和压缩的优化(ScriptBundle,StyleBundle,Bund
    zen coding de 一些快捷功能
    C# Xpath
    一个SQL SERVER查询分析器非常好用的工具
    探索MSSQL执行计划
    博客园武林人士
  • 原文地址:https://www.cnblogs.com/CHerish_OI/p/8793283.html
Copyright © 2011-2022 走看看