题意:给定一棵树,每个节点有一个颜色,问树上有多少种子串(定义子串为某两个点上的路径),保证叶子节点数<=20。n<=10^5

题解:

叶子节点小于等于20,考虑将每个叶子节点作为根把树给提起来形成一棵trie,然后定义这棵树的子串为从上到下的一个串(深度从浅到深)。

这样做我们可以发现每个子串必定是某棵trie上的一段直线。统计20棵树的不同子串只需要把它们建到一个自动机上就行了,相当于把20棵trie合并成一棵大的。
对于每个节点x,它贡献的子串数量是max[x]-min[x],又因为min[x]=max[fa]+1,则=max[x]-max[fa],就是step[x]-step[fa];
学会了怎样在sam上插入一颗trie,就直接记录一下父亲在sam上的节点作为p。注意每次都要新开一个点,不然会导致无意义的子串出现。

例如一棵树 (括号内为i颜色)

1(0)

2(1)

3(2)  4(3)

2是1的孩子,3和4都是2的孩子。在以1为根节点的时候插入了这棵trie,在以3为根节点的时候son[root][2]已经存在,如果用它来当现在的点的话就会让一棵trie接在另一棵的末位,导致无意义的子串出现,答案偏大。

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std; typedef long long LL;
const int N=*;
int n,c,tot,len,last;
int w[N],son[N][],step[N],pre[N],first[N],cnt[N],id[N];
struct node{
int x,y,next;
}a[*N]; void ins(int x,int y)
{
a[++len].x=x;a[len].y=y;
a[len].next=first[x];first[x]=len;
} int add_node(int x)
{
step[++tot]=x;
return tot;
} int extend(int p,int ch)
{
// int np;
// if(son[p][ch]) return son[p][ch];
// else np=add_node(step[p]+1);
int np=add_node(step[p]+);//debug 每次都要新开一个点 while(p && !son[p][ch]) son[p][ch]=np,p=pre[p];
if(p==) pre[np]=;
else
{
int q=son[p][ch];
if(step[q]==step[p]+) pre[np]=q;
else
{
int nq=add_node(step[p]+);
memcpy(son[nq],son[q],sizeof(son[q]));
pre[nq]=pre[q];
pre[np]=pre[q]=nq;
while(son[p][ch]==q) son[p][ch]=nq,p=pre[p];
}
}
last=np;
return np;
} void dfs(int x,int fa,int now)
{
int nt=extend(now,w[x]);
// printf("%d\n",nt);
for(int i=first[x];i;i=a[i].next)
{
int y=a[i].y;
if(y!=fa) dfs(y,x,nt);
}
} int main()
{
freopen("a.in","r",stdin);
scanf("%d%d",&n,&c);
for(int i=;i<=n;i++) scanf("%d",&w[i]);
tot=;len=;
memset(son,,sizeof(son));
memset(pre,,sizeof(pre));
memset(cnt,,sizeof(cnt));
memset(first,,sizeof(first));
step[++tot]=;last=;
for(int i=;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
ins(x,y);ins(y,x);
cnt[x]++;cnt[y]++;
}
// for(int i=1;i<=len;i++) printf("%d -- > %d\n",a[i].x,a[i].y);
for(int i=;i<=n;i++)
{
if(cnt[i]==) dfs(i,,);
}
// for(int i=1;i<=tot;i++) printf("%d ",id[i]);printf("\n");
LL ans=;
for(int i=;i<=tot;i++) ans+=(LL)(step[i]-step[pre[i]]);
printf("%lld\n",ans);
return ;
}

【bzoj3926- [Zjoi2015]诸神眷顾的幻想乡】广义sam的更多相关文章

  1. BZOJ3926:[ZJOI2015]诸神眷顾的幻想乡(广义SAM)

    Description 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日. 粉丝们非常热情,自发组织表演了一系列节目给幽香看. ...

  2. BZOJ3926 [Zjoi2015]诸神眷顾的幻想乡 字符串 SAM

    原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ3926.html 题目传送门 - BZOJ3926 题意 给定一个有 $n$ 个节点,最多只有 $20$ ...

  3. bzoj3926: [Zjoi2015]诸神眷顾的幻想乡 广义后缀自动机模板

    #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #d ...

  4. Luogu P3346 [ZJOI2015]诸神眷顾的幻想乡 广义SAM 后缀自动机

    题目链接 \(Click\) \(Here\) 真的是好题啊-不过在说做法之前先强调几个自己总是掉的坑点. 更新节点永远记不住往上跳\(p = fa[p]\) 新建节点永远记不住\(len[y] = ...

  5. bzoj3926: [Zjoi2015]诸神眷顾的幻想乡 对[广义后缀自动机]的一些理解

    先说一下对后缀自动机的理解,主要是对构造过程的理解. 构造中,我们已经得到了前L个字符的后缀自动机,现在我们要得到L+1个字符的后缀自动机,什么需要改变呢? 首先,子串$[0,L+1)$对应的状态不存 ...

  6. 【BZOJ3926】[Zjoi2015]诸神眷顾的幻想乡 广义后缀自动机

    [BZOJ3926][Zjoi2015]诸神眷顾的幻想乡 Description 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝 ...

  7. BZOJ 3926: [Zjoi2015]诸神眷顾的幻想乡 [广义后缀自动机 Trie]

    3926: [Zjoi2015]诸神眷顾的幻想乡 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1124  Solved: 660[Submit][S ...

  8. [BZOJ3926][ZJOI2015]诸神眷顾的幻想乡(后缀自动机)

    日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日. 粉丝们非常热情,自发组织表演了一系列节目给幽香看.幽香当然也非常高兴啦.  这时幽香发现了一件非常有趣的事情,太阳花田有n块空地.在过去 ...

  9. BZOJ3926 Zjoi2015 诸神眷顾的幻想乡【广义后缀自动机】

    Description 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日. 粉丝们非常热情,自发组织表演了一系列节目给幽香看. ...

  10. BZOJ3926 [Zjoi2015]诸神眷顾的幻想乡 【广义后缀自动机】

    题目 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日. 粉丝们非常热情,自发组织表演了一系列节目给幽香看.幽香当然也非常高兴 ...

随机推荐

  1. stm32--FatFs调试过程(SPIFlash)

    移植方法参见我的另一篇博客:<stm32--FatFs移植(SPIFlash)>. 本文仅记录在初次移植完成后,遇到的问题,和解决的过程. 调试记录: 问题1:f_open返回3,即磁盘没 ...

  2. Java重写构造方法

    public class TestSuper { public static void main(String[] args) { new ChildClass("alex", 1 ...

  3. 【数据库】 SQL 使用注意点

    [数据库] SQL 使用注意点 一. 索引 1. 常用的搜索条件,都建议加上索引,但状态列除外(该列只有0,1或几个值,不需要加索引,因为没效果) 2. 查询时, 索引列不能做函数处理,会不走索引 3 ...

  4. Eclipse中JS文件红叉处理

    使用新版本的Eclipse 或者 MyEclipse,项目中的 JS文件出现红叉,让人觉得项目中存在错误代码,给人的感觉很不爽. 记录一下去掉红叉的方法: 第1步: 打开工作空间中的项目找到项目的 . ...

  5. React开发时候注意点

    JSX 使用jsx的使用,用一个{}包裹起来,例如 const method = {<div> 123 </div>} 使用()小括号,防止分号自动插入 const eleme ...

  6. MySQL☞insert value与values

    最近公司事情太忙,作为以一挑十的测试,只能苦逼的累死累活的.好不容易临近上线,可以偷个懒写个文章. 简单的说说如何向表中插入数据: 1.向表中所有的列插入数据(插入多行数据): insert  int ...

  7. Google无法离线安装扩展程序

    Google无法离线安装扩展程序 Chrome插件伴侣 按照里面的使用说明使用 网盘地址: 链接: https://pan.baidu.com/s/1eXoLXyPNl2pfoPnArHq2Lg 提取 ...

  8. Spark搭档Elasticsearch

    Spark与elasticsearch结合使用是一种常用的场景,小编在这里整理了一些Spark与ES结合使用的方法.一. write data to elasticsearch利用elasticsea ...

  9. Go基础篇【第6篇】: 内置库模块 flag

    import "flag" flag包实现了命令行参数的解析.每个参数认为一条记录,根据实际进行定义,到一个set集合.每条都有各自的状态参数. 在使用flag时正常流程: 1.  ...

  10. 走进Android系统

    一.Android背景 [Android定义] Android是Google公司在2007年11月5日公布的基于Linux平台的开源手机操作系统. [发展历程] 2005年,Google收购企业And ...