题意:给定一棵树,每个节点有一个颜色,问树上有多少种子串(定义子串为某两个点上的路径),保证叶子节点数<=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. 大数据培训班 cloudera公司讲师面对面授课 CCDH CCAH CCP

    大数据助力成就非凡.大数据正在改变着商业游戏规则,为企业解决传统业务问题带来变革的机遇.毫无疑问,当未来企业尝试分析现有海量信息以推动业务价值增值时,必定会采用大数据技术. 目前对大数据的分析工具,首 ...

  2. java堆内存模型

     广泛地说,JVM堆内存被分为两部分——年轻代(Young Generation)和老年代(Old Generation). 年轻代 年轻代是所有新对象产生的地方.当年轻代内存空间被用完时,就会触发垃 ...

  3. Qt Qwdget 汽车仪表知识点拆解2 图像放大

    先贴上效果图,注意,没有写逻辑,都是乱动的 这里讲下 这个小汽车的进入过程,其实这个说白了就没有技术含量了,本来应该趁着这个机会学习一下Qt的动画机制,不过随机一想,这个自己写也累不到那里去 下面说下 ...

  4. Ubuntu 安装Qt

    下载Qt,这里步骤略过 设置共享, 如果设置共享没有问题,可以不看下面的 如果设置共享,在Ubuntu中找不到共享文件的话,那安找下面的步骤在来一次. http://blog.csdn.net/z60 ...

  5. Oracle数据库抽数神器toad

    使用了toad,再也不怕抽数成各种 文件格式,以及添加分割的数据文件了.百度搜toad,

  6. HDU 3269 P2P File Sharing System(模拟)(2009 Asia Ningbo Regional Contest)

    Problem Description Peer-to-peer(P2P) computing technology has been widely used on the Internet to e ...

  7. 第十四次ScrumMeeting会议

    第十三次Scrum Meeting 时间:2017/12/2 地点:咖啡馆 人员:策划组美工组 目前工作情况 名字 完成的工作 计划工作 蔡帜 科技树策划设计,科技图鉴蓝图设计 员工方面细节设定 游心 ...

  8. C#-WinForm控制输入框只接受数字输入

    背景 给导师上一节c#编写数据库应用程序的课,模拟ATM自助取款机的功能写了个winForm程序,关于金额的输入肯定是数字,因此避免输入格式不正确的数字带来异常,直接在输入时进行校验. 封装函数 C# ...

  9. lintcode-135-数字组合

    135-数字组合 给出一组候选数字(C)和目标数字(T),找到C中所有的组合,使找出的数字和为T.C中的数字可以无限制重复被选取. 例如,给出候选数组[2,3,6,7]和目标数字7,所求的解为: [7 ...

  10. 个人作业Week3-案例分析(201521123103 吴雅娟)

    根据博客要求,写一篇个人随笔 参考来自: http://www.cnblogs.com/xinz/archive/2012/03/26/2417699.html: http://www.cnblogs ...