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爬虫实例(六)多进程下载金庸网小说
目标任务:使用多进程下载金庸网各个版本(旧版.修订版.新修版)的小说 代码如下: # -*- coding: utf-8 -*- import requests from lxml import et ...
- B. Berland National Library---cf567B(set|模拟)
题目链接:http://codeforces.com/problemset/problem/567/B 题意:题目大意: 一个计数器, +号代表一个人进入图书馆, -号代表一个人出去图书馆. 给一个 ...
- AndroidStudio 3.3+ ButterKnife R2 红名问题
如果你一直用着ButterKnife,但是用的低版本(比如用得很多的8.4.0),然后在多module项目中一定知道要把R改成R2 然后最近如果升级AndroidStudio了,升到3.3以上(201 ...
- python float()
1.函数功能将一个数值或者字符转换成浮点型数值 >>> a = 12345 >>> amount = float(a) >>> print(amo ...
- ext3日志模式
ext3日志模式 http://blog.sina.com.cn/s/blog_5d4ab4b40100dosx.html ext3支持多种日志模式 ext3 是ext2文件系统的高一级版本,完全兼容 ...
- MySQL · 功能分析 · 5.6 并行复制实现分析
背景 我们知道MySQL的主备同步是通过binlog在备库重放进行的,IO线程把主库binlog拉过去存入relaylog,然后SQL线程重放 relaylog 中的event,然而这种模式有一个问题 ...
- 学JS必看-JavaScript数据结构深度剖析
回归简单 要理解JavaScript,你得首先放下对象和类的概念,回到数据和代码的本原.前面说过,编程世界只有数据和代码两种基本元素,而这两种元素又有着纠缠不清的关系.JavaScript就是把数据和 ...
- modelform和modelserializer
modelform modelform比form强悍很多
- Java多线程的下载器(1)
实现了一个基于Java多线程的下载器,可提供的功能有: 1. 对文件使用多线程下载,并显示每时刻的下载速度. 2. 对多个下载进行管理,包括线程调度,内存管理等. 一:单个文件下载的管理 1. 单文件 ...
- php array_rand()函数从数组中随机选择一个或多个元素
php使用array_rand()函数从数组中随机选择一个或多个元素的方法. 使用array_rand() 函数从数组中随机选出一个或多个元素,并返回. array_rand(array,numbe ...