cogs 2223. [SDOI2016 Round1] 生成魔咒
★★☆ 输入文件:menci_incantation.in 输出文件:menci_incantation.out 简单对比
时间限制:1 s 内存限制:128 MB
【题目描述】
魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示。例如可以将魔咒字符 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 次操作加入的魔咒字符。
【输出格式】
输出 n 行,每行一个数。第 i 行的数表示第 i 次操作后 S 的生成魔咒数量。
【样例输入】
7
1 2 3 3 3 1 2
【样例输出】
1
3
6
9
12
17
22
【提示】
对于 10% 的数据,1≤n≤10。
对于 30% 的数据,1≤n≤100。
对于 60% 的数据,1≤n≤1000。
对于 100% 的数据,1≤n≤100000。
用来表示魔咒字符的数字 x 满足 1≤x≤10^9。
题解:
题意是在一个字符串后面加上一个字符,问加上这个字符后现在有多少本质不同的字符串。
询问不同子串个数,想到后缀数组的一个经典应用,就是通过height[]来求一个字符串中有多少本质不同的子串。对于这个问题,我们可以想,每个子串都是某个后缀的前缀,那么问题就转化成了对于每一个后缀,求出它能贡献出的与以前不同的前缀的个数,答案累加即可。举几个例子可以发现,每个后缀贡献的答案就是这个后缀的长度减去以前的后缀与此后缀的LCP的最大值,而这个最大值就是height[i]。
对于这个题,由于字符串是由空字符一个一个添加并一个一个询问的,所以可以先把字符串翻转,转化成后缀数组的形式,答案就是求当前这个串的长度减去已有的串和它LCP的最大值。关键就是怎么求这个LCP,这个值由第二段的描述可以看出,假设当前串的rank=k,和它构成LCP的最大值的串的rank应该是k+1或K-1。这个可以用 hash+二分+set维护,set来找前驱和后继,二分用来比较两个字符串的大小,原理就是二分出两个串的LCP,判断下一位的大小即可。
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ULL;
const int maxn=;
const ULL BASE=1e9+;
int N,now;
ULL a[maxn],base[maxn],hash[maxn],ANS;
inline ULL get_hash(ULL from,ULL len){
return hash[from]-hash[from+len]*base[len];
}
inline int find(int l,int r,int f1,int f2){
if(l+>=r){
if(get_hash(f1,r)==get_hash(f2,r)) return r;
else return l;
}
int mid=(l+r)>>;
if(get_hash(f1,mid)==get_hash(f2,mid)) return find(mid,r,f1,f2);
else return find(l,mid-,f1,f2);
}
struct cmp{
bool operator()(const int &aa,const int &bb){
int len=find(,1e5,aa,bb);
return a[aa+len]<a[bb+len];
}
};
set<int,cmp> S;
set<int,cmp>::iterator tmp1,tmp2;
int main(){
scanf("%d",&N);
base[]=; for(int i=;i<=N;i++) base[i]=base[i-]*BASE;
for(int i=N;i>=;i--){
scanf("%d",&a[i]); now=;
hash[i]=hash[i+]*BASE+a[i];
tmp1=S.insert(i).first;
tmp2=tmp1;
if(tmp1!=S.begin()){
tmp1--;
now=find(,1e5,i,*tmp1);
}
if(++tmp2!=S.end()){
now=max(now,find(,1e5,i,*tmp2));
}
ANS+=(ULL)N-i+-now;
printf("%llu\n",ANS);
}
return ;
}
cogs 2223. [SDOI2016 Round1] 生成魔咒的更多相关文章
- cogs2223 [SDOI2016 Round1] 生成魔咒
cogs2223 [SDOI2016 Round1] 生成魔咒 原题链接 题解 暴力:每次更新后缀数组??? set+二分+hash暴力 http://paste.ubuntu.com/2549629 ...
- cogs2223. [SDOI2016 Round1] 生成魔咒(后缀数组 hash 二分 set
题意:对一个空串每次在后面加一个字符,问每加完一次得到的字符串有几个不同的子串. 思路:每个子串都是某个后缀的前缀,对于每个后缀求出他能贡献出之前没有出现过的前缀的个数,答案累加就行. 要求每个后缀的 ...
- liberOJ #2033. 「SDOI2016」生成魔咒 后缀数组
#2033. 「SDOI2016」生成魔咒 题目描述 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示.例如可以将魔咒字符 1 11.2 22 拼凑起来形成一个魔咒串 [1,2] [1, 2] ...
- 【BZOJ4516】【SDOI2016】生成魔咒 [SAM]
生成魔咒 Time Limit: 10 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Description 魔咒串由许多魔咒字符组成,魔咒字符 ...
- 【LOJ】 #2033. 「SDOI2016」生成魔咒
题解 就是字符集较大需要离散化和建边表的后缀自动机水题 每次会加入i个新的串,其中重复的就是i的父亲节点所在节点的长度,减掉即可 代码 #include <iostream> #inclu ...
- BZOJ4516: [Sdoi2016]生成魔咒 后缀自动机
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #inclu ...
- BZOJ 4516: [Sdoi2016]生成魔咒 [后缀自动机]
4516: [Sdoi2016]生成魔咒 题意:询问一个字符串每个前缀有多少不同的子串 做了一下SDOI2016R1D2,题好水啊随便AK 强行开map上SAM 每个状态的贡献就是\(Max(s)-M ...
- BZOJ_4516_[Sdoi2016]生成魔咒_后缀数组+ST表+splay
BZOJ_4516_[Sdoi2016]生成魔咒_后缀数组+ST表+splay Description 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示.例如可以将魔咒字符 1.2 拼凑起来形成一个魔 ...
- P4070 [SDOI2016]生成魔咒
题目地址:P4070 [SDOI2016]生成魔咒 相信看到题目之后很多人跟我的思路是一样的-- 肯定要用 SA(P3809 [模板]后缀排序) 肯定要会求本质不同的子串个数(P2408 不同子串个数 ...
随机推荐
- disk_free_space
$df = disk_free_space('/')/1024/1024/1024; $df_c = disk_free_space("c:"); $df_d = disk_fre ...
- Django实现微电影网站
主要实现功能: 注册,登陆,播放视频,评论视频,xadmin实现后台提供视频管理,权限管理等等 首页(搜索,筛选) 搜索页面 播放页面 个人中心 后台 源码下载 环境配置:python2.7 pip ...
- model方法取值总结
转自:https://www.cnblogs.com/ajianbeyourself/p/3604332.html
- 食物链--poj1182(并查集含有关系)
http://poj.org/problem?id=1182 题意应该就不用说了 再次回到食物链这道题,自己写了一遍,一直wa...原因竟然是不能用多实例,我也是醉了,但是我真的彻底的理解了,那 ...
- 学习grunt四解决yo webapp生成的是gulpfile而不是gruntfile问题
虽然gulp慢慢取代了gruntfile,但是还有大部分的github源码保留gruntfile,另外我们开发项目也不是全用gulp,也是用grunt. 但是yeoman上generator-weba ...
- 如何设置dedecms自定义表单必填项?
用dedecms自定义表单可以制作一个简单的预约系统,有些相关信息需要设置为必填项,比如联系方式,没有留下真实的电话或其他信息,以后要怎么联系到你的客户.那我们要如何设置织梦cms自定义表单必填项呢? ...
- Miller_Rabbin算法判断大素数,Pollard_rho算法进行质因素分解
Miller-rabin算法是一个用来快速判断一个正整数是否为素数的算法.它利用了费马小定理,即:如果p是质数,且a,p互质,那么a^(p-1) mod p恒等于1.也就是对于所有小于p的正整数a来说 ...
- makefile 中wildcard
在Makefile规则中,通配符会被自动展开.但在变量的定义和函数引用时,通配符将失效.这种情况下如果需要通配符有效,就需要使用函数“wildcard”,它的用法是:$(wildcard PATTER ...
- Tomcat清空缓存方法
把Tomcat的work目录下有个Catalina全部删除
- 【Cocos2dx 3.3】图片裁剪
从一个图片集中裁剪出需要的图片时,采用的坐标是屏幕坐标系: 示例如下: 图片:res/Images/grossini_dance_atlas.png ,每个人物大小为85* ...