zoukankan      html  css  js  c++  java
  • 【BZOJ3926】诸神眷顾的幻想乡 【广义后缀自动机】

    题意

      给定一棵树,每个结点有一个颜色,问树上有多少种子串(定义子串为两点上路径颜色的序列)。保证叶子结点<=20

    分析

      我们可以发现一个结论,任意一个子串一定是以某个叶子结点为根的trie的后缀。我们有注意到,叶子节点最多只有20,那么我们可以将每个叶子结点拿出来,以它为根按照trie树的方式插到广义后缀自动机中。要统计一共有多少子串的话,这样这样建好自动机以后枚举每个状态,然后res+=st[u].len-st[st[u].link].len;

      

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <iostream>
     5 
     6 using namespace std;
     7 const int maxn=100000+100;
     8 typedef long long LL;
     9 int val[maxn];
    10 int head[maxn],Next[2*maxn],to[2*maxn],deg[maxn];
    11 int N,sz,C;
    12 int cnt,cur;
    13 struct state{
    14     int len,link;
    15     int next[12];
    16 }st[40*maxn];
    17 
    18 void init(){
    19     sz=0;
    20     memset(head,-1,sizeof(head));
    21     cnt=1;
    22     cur=0;
    23     st[0].link=-1;
    24     st[0].len=0;
    25 }
    26 
    27 void add_edge(int a,int b){
    28     ++sz;
    29     to[sz]=b;
    30     Next[sz]=head[a];
    31     head[a]=sz;
    32 }
    33 
    34 int build_sam(int c,int last){
    35     cur=cnt++;
    36     st[cur].len=st[last].len+1;
    37     int p;
    38     for(p=last;p!=-1&&st[p].next[c]==0;p=st[p].link)
    39         st[p].next[c]=cur;
    40     if(p==-1)
    41         st[cur].link=0;
    42     else{
    43         int q=st[p].next[c];
    44         if(st[q].len==st[p].len+1)
    45             st[cur].link=q;
    46         else{
    47             int clone=cnt++;
    48             st[clone].len=st[p].len+1;
    49             st[clone].link=st[q].link;
    50             for(int i=0;i<C;i++)
    51                 st[clone].next[i]=st[q].next[i];
    52             for(;p!=-1&&st[p].next[c]==q;p=st[p].link)
    53                 st[p].next[c]=clone;
    54             st[cur].link=st[q].link=clone;
    55         }
    56     }
    57     return cur;
    58 }
    59 
    60 void dfs(int u,int fa,int las){
    61     int Las=build_sam(val[u],las);
    62     for(int i=head[u];i!=-1;i=Next[i]){
    63         int v=to[i];
    64         if(v==fa)continue;
    65         dfs(v,u,Las);
    66     }
    67     return;
    68 }
    69 
    70 int main(){
    71     scanf("%d%d",&N,&C);
    72     for(int i=1;i<=N;i++)
    73         scanf("%d",&val[i]);
    74     int a,b;
    75     init();
    76     for(int i=1;i<N;i++){
    77         scanf("%d%d",&a,&b);
    78         add_edge(a,b);
    79         add_edge(b,a);
    80         deg[a]++;deg[b]++;
    81     }
    82     for(int i=1;i<=N;i++){
    83         if(deg[i]==1){
    84             dfs(i,-1,0);
    85         }
    86     }
    87     LL ans=0;
    88     for(int i=0;i<cnt;i++){
    89         int p=st[i].link;
    90         if(p!=-1){
    91             ans+=st[i].len-st[p].len;
    92         }
    93     }
    94     printf("%lld
    ",ans);
    95 return 0;
    96 }
    View Code
  • 相关阅读:
    maven插件安装与使用
    java面试题
    关于java的GC
    技术人员要树立自己的品牌
    为什么IT公司都应该鼓励开源
    你应该坚持写博客 即使没有读者
    计算机基础
    收藏 | 产品经理不可不知的 7 种技术思维
    我讨厌你公事公办的样子
    子序列问题【LIS、LCS、LCIS】
  • 原文地址:https://www.cnblogs.com/LQLlulu/p/9892249.html
Copyright © 2011-2022 走看看