BZOJ4516:[SDOI2016]生成魔咒——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=4516
魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示。例如可以将魔咒字符 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 共有多少种生成魔咒。
SAM傻逼题,然而我把SAM忘光了?
没关系SAM怎么建我还记得,咦SAM怎么统计不同字符串个数来着?
于是我看了一眼BZOJ3998:[TJOI2015]弦论。
我们知道只要遍历后缀自动机就能得到所有不相同的子串,相当于每个节点有价值size=1,如果我们倒序遍历并且累加的话就能求出sum。
当然我们没必要每次都求一遍sum,我们发现我们新加入的节点,其造成的贡献按照我们上面的推论就是tr[np].l-tr[tr[np].fa].l。
(你可以试着画一个简单的后缀自动机感受一下,比如说“1231”,你就会发现实际造成贡献的就是fa~np的每个节点(除np)都由np转移来了+1,这些1需要累加到一起汇总到root,当然同理对于我们因为right集合不同而新开的点也是一样的。)
没了,很水吧。
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<cstdio>
#include<cctype>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
#define fi first
#define se second
const int N=1e5+;
inline int read(){
int X=,w=;char ch=;
while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
while(isdigit(ch))X=(X<<)+(X<<)+(ch^),ch=getchar();
return w?-X:X;
}
map<int,int>::iterator it;
struct node{
map<int,int>a;
int fa,l;
}tr[N<<];
int n,last,cnt;
ll ans;
inline void insert(int c){
int p=last,np=++cnt;
last=np;tr[np].l=tr[p].l+;
for(;p&&!tr[p].a[c];p=tr[p].fa)tr[p].a[c]=np;
if(!p)tr[np].fa=;
else{
int q=tr[p].a[c];
if(tr[p].l+==tr[q].l)tr[np].fa=q;
else{
int nq=++cnt;tr[nq].l=tr[p].l+;
for(it=tr[q].a.begin();it!=tr[q].a.end();it++)
tr[nq].a[it->fi]=it->se;
tr[nq].fa=tr[q].fa;tr[q].fa=tr[np].fa=nq;
for(;tr[p].a[c]==q;p=tr[p].fa)tr[p].a[c]=nq;
}
}
ans+=tr[np].l-tr[tr[np].fa].l;
}
int main(){
n=read();
last=cnt=;
for(int i=;i<=n;i++){
insert(read());printf("%lld\n",ans);
}
return ;
}
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++
BZOJ4516:[SDOI2016]生成魔咒——题解的更多相关文章
- BZOJ4516: [Sdoi2016]生成魔咒 后缀自动机
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #inclu ...
- BZOJ4516 [Sdoi2016]生成魔咒 【后缀自动机】
题目 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示.例如可以将魔咒字符 1.2 拼凑起来形成一个魔咒串 [1,2]. 一个魔咒串 S 的非空字串被称为魔咒串 S 的生成魔咒. 例如 S=[1,2, ...
- [bzoj4516][Sdoi2016]生成魔咒——后缀自动机
Brief Description 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示.例如可以将魔咒字符 1.2 拼凑起来形成一个魔咒串 [1,2]. 一个魔咒串 S 的非空字串被称为魔咒串 S 的生 ...
- BZOJ4516 SDOI2016生成魔咒(后缀数组+平衡树)
一个字符串本质不同的子串数量显然是总子串数减去所有height值.如果一个个往里加字符的话,每次都会改动所有后缀完全没法做.但发现如果从后往前加的话,每次只会添加一个后缀.于是我们把字符串倒过来,每次 ...
- bzoj4516: [Sdoi2016]生成魔咒 sam
题意:每次插入一个数字,查询本质不同的子串有多少个 题解:sam,数字很大,ch数组用map来存,每次ins之后查询一下新建点表示多少个本质不同的子串(l[np]-l[fa[np]]) /****** ...
- bzoj千题计划283:bzoj4516: [Sdoi2016]生成魔咒(后缀数组)
http://www.lydsy.com/JudgeOnline/problem.php?id=4516 考虑在后面新加一个字母产生的影响 假设是第i个 如果不考虑重复,那么会增加i个不同的字符串 考 ...
- BZOJ4516: [Sdoi2016]生成魔咒
果然SA比SAM+map快~加了fread目前rank1. 首先这是SAM裸题,然而SA求本质不同子串个数也很容易.考虑倒着建SA,这样没错加一个字符就变成加一个后缀,其他后缀都不变,那么i的答案就是 ...
- 2018.12.23 bzoj4516: [Sdoi2016]生成魔咒(后缀自动机)
传送门 samsamsam入门题. 题意简述:给出一个串让你依次插入字符,求每次插入字符之后不同子串的数量. 显然每次的变化量只跟新出现的nnn个后缀有关系,那么显然就是maxlenp−maxlenl ...
- BZOJ4516: [Sdoi2016]生成魔咒(后缀数组 set RMQ)
题意 题目链接 Sol 毒瘤SDOI 终于有一道我会做的题啦qwq 首先,本质不同的子串的个数 $ = \frac{n(n + 1)}{2} - \sum height[i]$ 把原串翻转过来,每次就 ...
随机推荐
- 【费元星】crt 无法上传文件,总是显示盾牌表示-完美解决
将如下内容保存到文件中,已.bat 结尾 taskkill /f /im explorer.exeattrib -s -r -h "%userprofile%\AppData\Local\i ...
- ajax跨域请求php
在众多站群中,不同功能的系统使用独立的一个域名,各系统之间存在相互调用的关系.使用js的XMLHttpRequest调用其他域名提示跨域权限不足.有些可能认为都同属于同一个顶级域名或者说域名一模一样怎 ...
- hdu5698瞬间移动(杨辉三角+快速幂+逆元)
瞬间移动 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submis ...
- python爬虫实例大全
WechatSogou [1]- 微信公众号爬虫.基于搜狗微信搜索的微信公众号爬虫接口,可以扩展成基于搜狗搜索的爬虫,返回结果是列表,每一项均是公众号具体信息字典. DouBanSpider [2]- ...
- 【WXS数据类型】RegExp
生成 regexp 对象需要使用 getRegExp函数,注意与JS的使用方法不同( new RegExp(pattern,modifiers);) 原型:getRegExp(pattern, mod ...
- ORACLE高级部分内容
1.pl/sql基本语句 DECLARE BEGIN END; / 循环语句 DECLARE I NUMBER(2):=1; BEGIN WHILE I<100 LOOP I:=I+1; EN ...
- idea clion编译器
RNMV64P0LA-eyJsaWNlbnNlSWQiOiJSTk1WNjRQMExBIiwibGljZW5zZWVOYW1lIjoiY24gdHUiLCJhc3NpZ25lZU5hbWUiOiIiL ...
- 【备忘】mysql常用操作汇总
1.增删改查 // 插入一条数据 insert into tableName values('liu','bei') // 删除一条数据 delete from tableName where las ...
- 上层应用与wpa_supplicant,wpa_supplicant与kernel 相关socket创建交互分析
单独拿出来,分析以下上层应用与wpa_supplicant wpa_supplicant与kernel 的socket交互. 关联上层应用与wpa_supplicant的socket的创建.连接流 ...
- python切片详解
先从原理上分析切片运算: list的切片,内部是调用__getitem__,__setitem__,__delitem__和slice函数.而slice函数又是和range()函数相关的. 给切片传递 ...