果然SA比SAM+map快。

首先这是SAM裸题,然而SA求本质不同子串个数也很容易。考虑倒着建SA,这样没错加一个字符就变成加一个后缀,其他后缀都不变,那么i的答案就是只考虑前i个后缀的答案。搞个双向链表,每次删一个后缀并RMQ更新答案。

(SAM+map复杂度可能是错的,但是我不清楚)

#include<algorithm>
#include<cstdio>
#define lb lower_bound
using namespace std;
const int N=1e5+5;
typedef int arr[N];
arr sa,r,f[17],c,v,s,t,p,q;
typedef long long ll;
ll b,z[N];
void pre(int*s,int n){
for(int i=0;i<n;++i)
++c[s[i]];
for(int i=1;i<n;++i)
c[i]+=c[i-1];
for(int i=n-1;~i;--i)
sa[--c[s[i]]]=i;
int m=0;
for(int i=1;i<n;++i)
r[sa[i]]=s[sa[i]]!=s[sa[i-1]]?++m:m;
for(int j=1;;j<<=1){
if(++m==n)break;
for(int i=0;i<j;++i)
v[i]=n-j+i;
for(int i=0;i<m;++i)
c[i]=0;
for(int i=0,k=j;i<n;++i){
if(sa[i]>=j)
v[k++]=sa[i]-j;
++c[r[i]];
}
for(int i=1;i<m;++i)
c[i]+=c[i-1];
for(int i=n-1;~i;--i)
sa[--c[r[v[i]]]]=v[i],v[i]=r[i];
m=r[sa[0]]=0;
for(int i=1;i<n;++i)
r[sa[i]]=v[sa[i]]!=v[sa[i-1]]||v[sa[i]+j]!=v[sa[i-1]+j]?++m:m;
}
}
int ask(int i,int j){
int k=__lg(j-i+1);
return min(f[k][i],f[k][j-(1<<k)+1]);
}
struct buf{
char z[9<<17],*s;
buf():s(z){
z[fread(z,1,sizeof z,stdin)]=0;
}
operator int(){
int x=0;
while(*s<48)++s;
while(*s>32)
x=x*10+*s++-48;
return x;
}
}it;
int main(){
int n=it;
for(int i=n-1;~i;--i)
s[i]=t[i]=it;
sort(t,t+n);
for(int i=0;i<n;++i)
s[i]=lb(t,t+n,s[i])-t+1;
pre(s,n+1);
for(int i=0,j=0;i<n;++i){
if(j)--j;
while(s[i+j]==s[sa[r[i]-1]+j])++j;
f[0][r[i]]=j;
}
for(int j=1;n>>j;++j)
for(int i=0;i+(1<<j)-1<=n;++i)
f[j][i]=min(f[j-1][i],f[j-1][i+(1<<j-1)]);
for(int i=1;i<=n;++i)
b+=n-sa[i]-f[0][i];
for(int i=n;i>1;--i)
p[i]=i-1;
for(int i=1;i<n;++i)
q[i]=i+1;
for(int i=0;i<n;++i){
int j=r[i],k=0;
if(p[j])k=max(k,ask(p[j]+1,j));
if(q[j])k=max(k,ask(j+1,q[j]));
z[i]=b,b-=n-i-k;
p[q[j]]=p[j];
q[p[j]]=q[j];
}
for(int i=n-1;~i;--i)
printf("%lld\n",z[i]);
}

BZOJ4516: [Sdoi2016]生成魔咒的更多相关文章

  1. BZOJ4516: [Sdoi2016]生成魔咒 后缀自动机

    #include<iostream> #include<cstdio> #include<cstring> #include<queue> #inclu ...

  2. [bzoj4516][Sdoi2016]生成魔咒——后缀自动机

    Brief Description 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示.例如可以将魔咒字符 1.2 拼凑起来形成一个魔咒串 [1,2]. 一个魔咒串 S 的非空字串被称为魔咒串 S 的生 ...

  3. BZOJ4516 [Sdoi2016]生成魔咒 【后缀自动机】

    题目 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示.例如可以将魔咒字符 1.2 拼凑起来形成一个魔咒串 [1,2]. 一个魔咒串 S 的非空字串被称为魔咒串 S 的生成魔咒. 例如 S=[1,2, ...

  4. BZOJ4516 SDOI2016生成魔咒(后缀数组+平衡树)

    一个字符串本质不同的子串数量显然是总子串数减去所有height值.如果一个个往里加字符的话,每次都会改动所有后缀完全没法做.但发现如果从后往前加的话,每次只会添加一个后缀.于是我们把字符串倒过来,每次 ...

  5. bzoj4516: [Sdoi2016]生成魔咒 sam

    题意:每次插入一个数字,查询本质不同的子串有多少个 题解:sam,数字很大,ch数组用map来存,每次ins之后查询一下新建点表示多少个本质不同的子串(l[np]-l[fa[np]]) /****** ...

  6. 2018.12.23 bzoj4516: [Sdoi2016]生成魔咒(后缀自动机)

    传送门 samsamsam入门题. 题意简述:给出一个串让你依次插入字符,求每次插入字符之后不同子串的数量. 显然每次的变化量只跟新出现的nnn个后缀有关系,那么显然就是maxlenp−maxlenl ...

  7. bzoj千题计划283:bzoj4516: [Sdoi2016]生成魔咒(后缀数组)

    http://www.lydsy.com/JudgeOnline/problem.php?id=4516 考虑在后面新加一个字母产生的影响 假设是第i个 如果不考虑重复,那么会增加i个不同的字符串 考 ...

  8. BZOJ4516: [Sdoi2016]生成魔咒(后缀数组 set RMQ)

    题意 题目链接 Sol 毒瘤SDOI 终于有一道我会做的题啦qwq 首先,本质不同的子串的个数 $ = \frac{n(n + 1)}{2} - \sum height[i]$ 把原串翻转过来,每次就 ...

  9. BZOJ4516 SDOI2016生成魔咒(后缀自动机)

    本质不同子串数量等于所有点的len-parent树上父亲的len的和.可以直接维护. #include<iostream> #include<cstdio> #include& ...

随机推荐

  1. iOS 报错汇总

    1. Unknown type name 'class'; did you mean 'Class' 问题解决方法 objectice-c 工程中的类(比如 类 A)使用 C++ 文件时  A.m 文 ...

  2. React Native之 Navigator与NavigatorIOS使用

    前言 学习本系列内容需要具备一定 HTML 开发基础,没有基础的朋友可以先转至 HTML快速入门(一) 学习 本人接触 React Native 时间并不是特别长,所以对其中的内容和性质了解可能会有所 ...

  3. hadoop常用的操作命令

    1.显示hdfs上test目录下的所有文件列表 hadoop fs -ls /test/ 2.查看hdfs中的文件内容 hadoop fs -cat /daas/bstl/term/rawdt/201 ...

  4. jni操作jobject

    一. 注册JNI函数 1.         静态方法 一般使用javah进行编译,生成很长的文件名和函数名字,这个书写不方便,影响运行效率. 2.         动态注册 使用JNINativeMe ...

  5. 局域网象棋游戏(C++实现,使用Socket,界面使用Win32,CodeBlocks+GCC编译)

    目录 成果 运行效果图 过程 1. 首先的问题是下棋的两端应该是什么样的? 2. 接下来的问题是怎么表示,怎么存储? 3. 然后应该怎么通信呢? 代码 main.cpp chinese_chess.h ...

  6. Struts2中的Ognl

    OGNL(Object-Graph Navigation Language)全称为对象图导航语言,是一种功能强大的表达式语言,它通过简单一致的语法,可以任意存取对象的属性或者调用对象的方法,能够遍历整 ...

  7. [LeetCode] Wiggle Sort II 摆动排序

    Given an unsorted array nums, reorder it such that nums[0] < nums[1] > nums[2] < nums[3]... ...

  8. [LeetCode] Minimum Path Sum 最小路径和

    Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which ...

  9. openwrt下部署adbyby去广告大师 免luci 带自启动,自动开启透明代理

    最近朋友送了个360老路由器 C301,于是乎就掉进了智能路由器的坑, 玩智能路由器第一件事一定是去广告, 要么怎么对得起智能路由器- -! 路由器去广告当然首推广告屏蔽大师 www.adbyby.c ...

  10. LINUX操作系统VIM的安装和配置

    VIM的安装   在命令行敲入"vi"后按"tab"键,可以看到目前系统中只安装了vi和vim.tiny. vim是从VI发展而来的一个文本编辑器,功能更强大. ...