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 不同子串个数 ...
随机推荐
- python 基础 特殊符号的使用
python语句中的一些基本规则和特殊符号: 1.井号# 表示之后的字符为python注释 Python注释语句从#号字符开始,注释可以在语句的任何一个地方开始,解释器会忽略掉该行#号之后的所有内容 ...
- MySQL字符集的一个坑
MySQL字符集的一个坑 http://imysql.com/2013/10/29/misunderstand-about-charset-handshake.shtml MySQL字符集的一个坑 1 ...
- 划分LUN
划分LUN http://mp.weixin.qq.com/s?__biz=MzAwNzU3NzQ0MA==&mid=209842199&idx=1&sn=7d77fdf7a8 ...
- Unity 脚本的执行顺序
在Unity脚本中常用到的函数就是下面这些,他们的顺序也是按照箭头的方向执行的. Awake ->OnEable-> Start -> FixedUpdate-> Update ...
- linux基础(2)-基础命令和基础特性
基础命令 命令历史 命令历史的管理 登陆 shell 时,会读取命令历史文件中记录下的命令: ~/.bash_history . 登陆进 shell 后,新执行的命令只会记录在缓存中,这些命令会在用户 ...
- PHP 常用命令行
1.PHP运行指定文件 php -f test.php (-f 可省略) 2.命令行直接运行PHP代码 php -r "phpinfo();" 如果结果太长,还可以 php -r ...
- 尝试.Net Core—使用.Net Core + Entity FrameWork Core构建WebAPI(一)
想尝试.Net Core很久了,一直没有时间,今天回家,抛开一切,先搭建一个.Net Core的Demo出来玩玩. 废话少说,咱直奔主题: 一.开发环境 VS2015 Update3 Microsof ...
- JAVA 实现XML与JSON 相互转换
原文地址https://blog.csdn.net/congcong68/article/details/39029907 在工作中,经常碰到XML转为JSON或者JSON转为XML,在这过程中有时嵌 ...
- 简单的js动态显示当前时间
js中获取当前时间首先我们要new一个时间对象 var data = new Date(); 然后可以点出很多方法.获取不同的时间格式 自己可以去尝试
- c++虚函数重写的权限问题
cbase.h: #ifndef CBASE_H #define CBASE_H #include<iostream> using std::cout; using std::endl; ...