【BZOJ3926】[Zjoi2015]诸神眷顾的幻想乡 广义后缀自动机
【BZOJ3926】[Zjoi2015]诸神眷顾的幻想乡
Description
幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日。
Input
第一行两个正整数n,c。表示空地数量和颜色数量。
Output
一行,输出一个整数,表示答案。
Sample Input
0 2 1 2 1 0 0
1 2
3 4
3 5
4 6
5 7
2 5
Sample Output
HINT
对于所有数据,1<=n<=100000, 1<=c<=10。
题解:由于叶子数量只有20个,所以可以枚举叶子,以每个叶子为根,这样我们就相当于得到了一堆Trie树。
那么广义后缀自动机,就是在多个串,或者Trie树上建的后缀自动机。与普通SAM的区别就是,每次的last指针指向的是它在Trie树上的父亲 在后缀自动机上对应的节点。不过呢,如果你像普通SAM一样来建广义SAM,可能会多建出一些没用的点,不过由于本人懒,多建一些点就多建吧,反正影响不大。
然后这里问的是不同的子串的个数,答案就是每个点的mx-它的parent的mx。怎么理解呢?我们将parent树拎出来,每个点都可以当做一些子串的结束节点,在每个节点结束的子串数量就是mx,但是这样肯定有重复的,我们要减去之前已经被计算过的子串个数,也就是减去parent的mx就行了。
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int maxm=2000010;
const int maxn=200010;
int n,tot,cnt,last;
int ch[maxm][10],mx[maxm],pre[maxm];
int to[maxn],next[maxn],head[maxn],v[maxn],d[maxn];
long long ans;
int extend(int p,int x)
{
if(ch[p][x]&&mx[ch[p][x]]==mx[p]+1) return ch[p][x]; //这里可以防止多建点
int np=++tot;
mx[np]=mx[p]+1;
for(;p&&!ch[p][x];p=pre[p]) ch[p][x]=np;
if(!p) pre[np]=1;
else
{
int q=ch[p][x];
if(mx[q]==mx[p]+1) pre[np]=q;
else
{
int nq=++tot;
mx[nq]=mx[p]+1,pre[nq]=pre[q],pre[np]=pre[q]=nq;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
for(;p&&ch[p][x]==q;p=pre[p]) ch[p][x]=nq;
}
}
return np;
}
void dfs(int x,int fa,int p)
{
int i,np=extend(p,v[x]);
for(i=head[x];i!=-1;i=next[i]) if(to[i]!=fa) dfs(to[i],x,np);
}
void add(int a,int b)
{
to[cnt]=b,next[cnt]=head[a],head[a]=cnt++;
}
int main()
{
int i,a,b;
scanf("%d%d",&n,&a);
for(i=1;i<=n;i++) scanf("%d",&v[i]);
memset(head,-1,sizeof(head));
for(i=1;i<n;i++)
{
scanf("%d%d",&a,&b);
add(a,b),add(b,a);
d[a]++,d[b]++;
}
tot=1;
for(i=1;i<=n;i++) if(d[i]==1) dfs(i,0,1);
for(i=1;i<=tot;i++) ans+=mx[i]-mx[pre[i]];
printf("%lld",ans);
return 0;
}
【BZOJ3926】[Zjoi2015]诸神眷顾的幻想乡 广义后缀自动机的更多相关文章
- bzoj3926: [Zjoi2015]诸神眷顾的幻想乡 广义后缀自动机模板
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #d ...
- BZOJ 3926: [Zjoi2015]诸神眷顾的幻想乡 [广义后缀自动机 Trie]
3926: [Zjoi2015]诸神眷顾的幻想乡 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1124 Solved: 660[Submit][S ...
- BZOJ.3926.[ZJOI2015]诸神眷顾的幻想乡(广义后缀自动机)
题目链接 要对多个串同时建立SAM,有两种方法: 1.将所有串拼起来,中间用分隔符隔开,插入字符正常插入即可. 2.在这些串的Trie上建SAM.实际上并不需要建Trie,还是只需要正常插入(因为本来 ...
- 洛谷P3346 [ZJOI2015]诸神眷顾的幻想乡(广义后缀自动机)
题意 题目链接 Sol 广义SAM的板子题. 首先叶子节点不超过20,那么可以直接对每个叶子节点为根的子树插入到广义SAM中. 因为所有合法的答案一定是某个叶子节点为根的树上的一条链,因此这样可以统计 ...
- BZOJ 3926: [Zjoi2015]诸神眷顾的幻想乡 广义后缀自动机 后缀自动机 字符串
https://www.lydsy.com/JudgeOnline/problem.php?id=3926 广义后缀自动机是一种可以处理好多字符串的一种数据结构(不像后缀自动机只有处理一到两种的时候比 ...
- BZOJ 3926 [Zjoi2015]诸神眷顾的幻想乡 ——广义后缀自动机
神奇的性质,叶子节点不超过20个. 然后把这些节点提出来构成一颗新树,那么这些树恰好包含了所有的情况. 所以直接广义后缀自动机. 然后统计本质不同的字符串就很简单显然了. #include <c ...
- [ZJOI2015]诸神眷顾的幻想乡 广义后缀自动机_DFS_语文题
才知道题目中是只有20个叶子节点的意思QAQ.... 这次的广义后缀自动机只是将 last 设为 1, 并重新插入. 相比于正统的写法,比较浪费空间. Code: #include <cstdi ...
- BZOJ 3926: [Zjoi2015]诸神眷顾的幻想乡(广义后缀自动机 多串)
因为任何一条路径都可以看做某两个叶子节点之间路径的一部分,然后分别把20个叶节点当作根,把整棵树看作trie树,那么一条路径就能看作是从根到某个点这一条路的后缀,构建SAM就能维护不同子串的个数了. ...
- 【BZOJ3926】诸神眷顾的幻想乡(后缀自动机)
[BZOJ3926]诸神眷顾的幻想乡(后缀自动机) 题面 BZOJ 题解 广义后缀自动机啦 求多个串的不同子串个数? 当然是后缀自动机,最后只要把\(longest-parent.longest\)求 ...
随机推荐
- hdu 1283 最简单的计算机
水题. .. import java.util.Scanner; public class Main { static int m1, m2; static int r1, r2, r3; publi ...
- 针对访问uri 限制ip
在虚拟主机配置文件中加入如下字段: <filesmatch "(.*)admin(.*)"> Order deny,allow ...
- python gzip压缩
1 import urllib2 2 from StringIO import StringIO 3 import gzip 4 5 def loadData(url): 6 request = ur ...
- ElasticSearch refresh API
在 Elasticsearch 中,写入和打开一个新段的轻量的过程叫做 refresh . 默认情况下每个分片会每秒自动刷新一次.这就是为什么我们说 Elasticsearch 是 近 实时搜索: 文 ...
- 代码验证C#执行”文件打开关闭操作“耗时
2017-04-19 部门经理习惯用C#做数据清洗,遇到个需要验证的问题,在一个万次左右循环内对文件执行打开关闭操作,比在循环前打开文件.循环后关闭文件耗时多多少. using System; usi ...
- iOS: 学习笔记, 加入一个带界面约束的控制器
1. 创建一个空iOS应用程序(Empty Application). 2. 加入加控制器类. 改动控制器类的viewDidLoad - (void)viewDidLoad { [super view ...
- iOS代码覆盖率测试工具
基于lcov-1.11的:CodeCoverage4iOS 阅读目录 环境准备 Xcode工程配置 构建并安装程序 收集代码覆盖率 过滤结果 合并多个Coverage.info⽂件⽣成覆盖率报告: ...
- Android:Activity+Fragment及它们之间的数据交换(一)
简单介绍: 为什么要用Fragment?使用Fragment能够在一个Activity中实现不同的界面. Fragment与Fragment之间的动画切换,远比Activity与Activity之间的 ...
- Python基础之函数与装饰器
阅读目录 一.为什么要使用函数 二.函数的定义与调用 三.函数返回值 四.函数的参数 五.本章小结 六.装饰器 一.函数流程图: 函数名的命名规则: 1.函数名必须由字母下划线数字组成,不能是关键字和 ...
- AccessibilityService 官网介绍
AccessibilityService extends Service java.lang.Object ↳ android.content.Context ↳ android.co ...