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 }
  • 相关阅读:
    leetcode 279. Perfect Squares
    leetcode 546. Remove Boxes
    leetcode 312. Burst Balloons
    leetcode 160. Intersection of Two Linked Lists
    leetcode 55. Jump Game
    剑指offer 滑动窗口的最大值
    剑指offer 剪绳子
    剑指offer 字符流中第一个不重复的字符
    leetcode 673. Number of Longest Increasing Subsequence
    leetcode 75. Sort Colors (荷兰三色旗问题)
  • 原文地址:https://www.cnblogs.com/CHerish_OI/p/8793283.html
Copyright © 2011-2022 走看看