[Sdoi2016]生成魔咒

动态维护不同子串的数量

想想如果只要查询一次要怎么做,那就是计算各个点的\(len[u]-len[link[u]]\)然后求和即可,现在要求动态更新,我们可以保存一个答案,然后每次更新后缀链接的时候,如果是连接的话就要加上\(len[u]-len[link[u]]\),断开的话就要减去\(len[u]-len[link[u]]\),每次输出答案即可

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<string>
#include<algorithm>
#include<stack>
using namespace std;
void ____(){ ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0); }
const int MAXN = 2e5+7;
using LL = int_fast64_t; struct SAM{
int len[MAXN],link[MAXN],tot,last;
LL ret = 0;
map<int,int> ch[MAXN];
SAM(){ link[0] = -1; }
void extend(int x){
int np = ++tot, p = last;
len[np] = len[p] + 1;
while(p!=-1 and !ch[p].count(x)){
ch[p].insert(make_pair(x,np));
p = link[p];
}
if(p==-1) link[np] = 0;
else{
int q = ch[p][x];
if(len[p]+1==len[q]) link[np] = q;
else{
int clone = ++tot;
len[clone] = len[p] + 1;
link[clone] = link[q];
ret += len[clone] - len[link[clone]];
ch[clone] = ch[q];
ret -= len[q] - len[link[q]];
link[q] = link[np] = clone;
ret += len[q] - len[clone];
while(p!=-1 and ch[p].count(x) and ch[p].at(x)==q){
ch[p].at(x) = clone;
p = link[p];
}
}
}
last = np;
ret += len[np] - len[link[np]];
}
}sam;
int n;
int main(){
scanf("%d",&n);
for(int i = 1; i <= n; i++){
int x; scanf("%d",&x);
sam.extend(x);
printf("%lld\n",sam.ret);
}
return 0;
}

BZOJ 4516. [Sdoi2016]生成魔咒【SAM 动态维护不同子串数量】的更多相关文章

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

    4516: [Sdoi2016]生成魔咒 题意:询问一个字符串每个前缀有多少不同的子串 做了一下SDOI2016R1D2,题好水啊随便AK 强行开map上SAM 每个状态的贡献就是\(Max(s)-M ...

  2. 【刷题】BZOJ 4516 [Sdoi2016]生成魔咒

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

  3. BZOJ 4516: [Sdoi2016]生成魔咒(后缀数组)

    传送门 解题思路 题目其实就是动态维护本质不同的串的个数.考虑到只有加数字的操作,所以可以用后缀数组.题目是每次往后加数字,这样不好处理,因为每次加数字之后所有的后缀都会改变.所以要转化一下思路,就是 ...

  4. BZOJ 4516: [Sdoi2016]生成魔咒

    Description 给出一串数字,求每次插入一个数字后本质不同的子串. Sol SAM. 在 SAM 上添加节点的时候统计一下 \(val[np]-val[par[np]]\) 就可以了... 用 ...

  5. ●BZOJ 4516 [Sdoi2016]生成魔咒

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=4516 题解: 把串反过来后,问题变为求每个后缀的互不相同的子串个数.首先用倍增算法求出 sa ...

  6. BZOJ.4516.[SDOI2016]生成魔咒(后缀自动机 map)

    题目链接 后缀数组做法见这. 直接SAM+map.对于每个节点其产生的不同子串数为len[i]-len[fa[i]]. //15932kb 676ms #include <map> #in ...

  7. BZOJ 4516: [Sdoi2016]生成魔咒 后缀自动机 性质

    http://www.lydsy.com/JudgeOnline/problem.php?id=4516 http://blog.csdn.net/doyouseeman/article/detail ...

  8. BZOJ 4516: [Sdoi2016]生成魔咒——后缀数组、并查集

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4516 题意 一开始串为空,每次往串后面加一个字符,求本质不同的子串的个数,可以离线.即长度为 ...

  9. BZOJ 4516 [Sdoi2016]生成魔咒 ——后缀自动机

    本质不同的字串,考虑SA的做法,比较弱,貌似不会. 好吧,只好用SAM了,由于后缀自动机的状态最简的性质, 所有不同的字串就是∑l[i]-l[fa[i]], 然后后缀自动机是可以在线的,然后维护一下就 ...

随机推荐

  1. LeetCode237 删除链表中的节点

    请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点,你将只被给定要求被删除的节点. 现有一个链表 -- head = [4,5,1,9],它可以表示为: 4 -> 5 -> 1 - ...

  2. 行业动态 | 利用Cassandra数据库揭开家族祖先的秘密

        FamilySearch选择了基于Apache Cassandra的DataStax Enterprise (DSE)来加速用户增长,并通过更快的反应时间.高可用性以及零数据库宕机来提供强大的 ...

  3. Windows同一软件不同窗口如何快速切换

    windows快速切换应用的快捷键是Alt + Tab 这个快捷键可以在多个应用之间快速切换,但是软件多开时,而此时我只想在同一软件内的多个窗口切换,一切换好多个窗口扑面而来,我还要去用找并用鼠标点击 ...

  4. 【Oracle】常见等待事件处理

    1.查看数据库中需要关注的等待事件: select sw.seq#,sw.sid||','||s.serial# sids,s.username,sw.event,sw.P1,sw.p2,sw.p3, ...

  5. 【网络】trunk和vlan配置

    篇一 : trunk配置和vlan配置 trunk配置 Switch>enable ? ? ?//进入特权模式 Switch#conf t ? ? ?//进入配置模式 Switch(config ...

  6. leetcode 321. 拼接最大数(单调栈,分治,贪心)

    题目链接 https://leetcode-cn.com/problems/create-maximum-number/ 思路: 心都写碎了.... 也许就是不适合吧.... 你是个好人... cla ...

  7. v-model语法糖

    其实v-model就是一个结合了v-bind和v-on的语法糖,实现了双向数据绑定. 举个(栗子):

  8. PyTorch 于 JupyterLab 的环境准备

    PyTorch 是目前主流的深度学习框架之一,而 JupyterLab 是基于 Web 的交互式笔记本环境.于 JupyterLab 我们可以边记笔记的同时.边执行 PyTorch 代码,便于自己学习 ...

  9. Eclipse中给jar包导入JavaDoc的方法

    原文转载自:http://blog.csdn.net/mr_von/article/details/7740138 在使用Java语言开发的过程中,开发人员经常需要用到一些开源的工具包.在使用别人的j ...

  10. JAVA获取当前文件路径this.getClass().getResource方法详细讲解

    public class Test { public void run() { // TODO Auto-generated method stub System.out.println(" ...