BZOJ4516 [Sdoi2016]生成魔咒 【后缀自动机】
题目
魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示。例如可以将魔咒字符 1、2 拼凑起来形成一个魔咒串 [1,2]。
一个魔咒串 S 的非空字串被称为魔咒串 S 的生成魔咒。
例如 S=[1,2,1] 时,它的生成魔咒有 [1]、[2]、[1,2]、[2,1]、[1,2,1] 五种。S=[1,1,1] 时,它的生成魔咒有 [1]、
[1,1]、[1,1,1] 三种。最初 S 为空串。共进行 n 次操作,每次操作是在 S 的结尾加入一个魔咒字符。每次操作后都
需要求出,当前的魔咒串 S 共有多少种生成魔咒。
输入格式
第一行一个整数 n。
第二行 n 个数,第 i 个数表示第 i 次操作加入的魔咒字符。
1≤n≤100000。,用来表示魔咒字符的数字 x 满足 1≤x≤10^9
输出格式
输出 n 行,每行一个数。第 i 行的数表示第 i 次操作后 S 的生成魔咒数量
输入样例
7
1 2 3 3 3 1 2
输出样例
1
3
6
9
12
17
22
题解
用到后缀自动机的一个性质:
节点u所代表的子串数 = step[u] - step[pre[u]]
原因:
显然u所代表的子串数为[min(u),max(u)],其中min,max均代表从根到u的路径的长度最值
而且有这样一个性质:u父亲的max(fa) = min(u) - 1
所以u代表的子串数可以写成如上所示
我们只需要在每次建立父亲指针和断开父亲指针时维护答案就好了
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
using namespace std;
const int maxn = 200005,maxm = 100005,INF = 1000000000;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57) {out = (out << 3) + (out << 1) + c - '0'; c = getchar();}
return out * flag;
}
map<int,int> ch[maxn];
int pre[maxn],step[maxn],cnt,last,n;
LL ans;
int upd(int u){return step[u] - step[pre[u]];}
void ins(int x){
int p = last,np = ++cnt;
last = np; step[np] = step[p] + 1;
while (p && !ch[p].count(x)) ch[p][x] = np,p = pre[p];
if (!p) pre[np] = 1,ans += upd(np);
else {
int q = ch[p][x];
if (step[q] == step[p] + 1) pre[np] = q,ans += upd(np);
else {
int nq = ++cnt; step[nq] = step[p] + 1;
ch[nq] = ch[q]; pre[nq] = pre[q]; ans += upd(nq) - upd(q);
pre[np] = pre[q] = nq; ans += upd(np) + upd(q);
while (p && ch[p][x] == q) ch[p][x] = nq,p = pre[p];
}
}
}
int main(){
n = read(); int x; cnt = last = 1;
REP(i,n) x = read(),ins(x),printf("%lld\n",ans);
return 0;
}
BZOJ4516 [Sdoi2016]生成魔咒 【后缀自动机】的更多相关文章
- BZOJ4516: [Sdoi2016]生成魔咒 后缀自动机
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #inclu ...
- [bzoj4516][Sdoi2016]生成魔咒——后缀自动机
Brief Description 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示.例如可以将魔咒字符 1.2 拼凑起来形成一个魔咒串 [1,2]. 一个魔咒串 S 的非空字串被称为魔咒串 S 的生 ...
- BZOJ 4516: [Sdoi2016]生成魔咒 [后缀自动机]
4516: [Sdoi2016]生成魔咒 题意:询问一个字符串每个前缀有多少不同的子串 做了一下SDOI2016R1D2,题好水啊随便AK 强行开map上SAM 每个状态的贡献就是\(Max(s)-M ...
- BZOJ 4516: [Sdoi2016]生成魔咒 后缀自动机 性质
http://www.lydsy.com/JudgeOnline/problem.php?id=4516 http://blog.csdn.net/doyouseeman/article/detail ...
- BZOJ 4516 [Sdoi2016]生成魔咒 ——后缀自动机
本质不同的字串,考虑SA的做法,比较弱,貌似不会. 好吧,只好用SAM了,由于后缀自动机的状态最简的性质, 所有不同的字串就是∑l[i]-l[fa[i]], 然后后缀自动机是可以在线的,然后维护一下就 ...
- BZOJ.4516.[SDOI2016]生成魔咒(后缀自动机 map)
题目链接 后缀数组做法见这. 直接SAM+map.对于每个节点其产生的不同子串数为len[i]-len[fa[i]]. //15932kb 676ms #include <map> #in ...
- BZOJ4516: [Sdoi2016]生成魔咒(后缀数组 set RMQ)
题意 题目链接 Sol 毒瘤SDOI 终于有一道我会做的题啦qwq 首先,本质不同的子串的个数 $ = \frac{n(n + 1)}{2} - \sum height[i]$ 把原串翻转过来,每次就 ...
- [SDOI2016]生成魔咒(后缀自动机)
/* 水题, 根据性质做就行, nq不会对答案产生贡献, 那么只算p的贡献就好了 */ #include<cstdio> #include<algorithm> #includ ...
- [SDOI2016] 生成魔咒 - 后缀数组,平衡树,STL,时间倒流
[SDOI2016] 生成魔咒 Description 初态串为空,每次在末尾追加一个字符,动态维护本质不同的子串数. Solution 考虑时间倒流,并将串反转,则变为每次从开头删掉一个字符,即每次 ...
随机推荐
- EM理解(转)
EM是我一直想深入学习的算法之一,第一次听说是在NLP课中的HMM那一节,为了解决HMM的参数估计问题,使用了EM算法.在之后的MT中的词对齐中也用到了.在Mitchell的书中也提到EM可以用于贝叶 ...
- modprobe与insmod的区别
linux设备驱动有两种加载方式insmod和modprobe,下面谈谈它们用法上的区别1.insmod一次只能加载特定的一个设备驱动,且需要驱动的具体地址.写法为: insmod dr ...
- C# FileInfo 类
FileInfo类不像File类,它没有静态方法,仅可用于实例化的对像.FileInfo对像表示在磁盘或网络位置的文件,注意它不是流,为了读写文件,必须创建Stream对像. fileInfo类提供了 ...
- detection in video and image
video中的detection,背景更加复杂,目标更加不聚焦,同时由于图片分辨率低于图像,因此更加难做. image中的Detection,背景相对简单些,目标更加聚焦,同时图片分辨率高,因此更加容 ...
- es6中的promise解读
目录 什么是promise? promise的优点 回调地狱问题 Promise的三种状态 一个简单的promise promise中的then 利用promise解决回调地狱 promise的链式 ...
- 项目十八-Hadoop+Hbase分布式集群架构“完全篇”
本文收录在Linux运维企业架构实战系列 前言:本篇博客是博主踩过无数坑,反复查阅资料,一步步搭建,操作完成后整理的个人心得,分享给大家~~~ 1.认识Hadoop和Hbase 1.1 hadoop简 ...
- DNS服务初步搭建
一.准备DNS服务环境 选择 bind dns服务软件包 直接yum安装 bind 和 bind-utils 工具包,测试机器安装bind-utils测试工具包. 服务程序名为 named 二.配置D ...
- 正则表达式-基础知识Review
正则表达式(Regular Expression)是计算机科学的一个概念. 正则表达式使用单个字符窜来描述.匹配一系列符合某个句法规则的字符窜. 在很多文本编辑器里, 正则表达式通常用来被检索替换哪些 ...
- RPC框架 - thrift 客户端
-------客户端程序 ------ 下载 下载 thrift 源代码包 下载 thrift 的bin包 准备描述文件(使用源代码包的示例文件) \thrift-0.10.0\tu ...
- MTCNN学习进展
20190618 截止今日,学习了MTCNN预测部分的内容,包括三个网络输入输出之类的东西. 之后需要进一步学习的,NMS原理鞋机,MTCNN训练过程细节,损失函数细节