Description

你有一个字符串S,一开始为空串,要求支持两种操作

在S后面加入字母C

删除S最后一个字母

问每次操作后S有多少个两两不同的连续子串

Solution

先忽略删除操作,建出最终的串的 \(SAM\),构建过程的所有可能的串的 \(SAM\) 都包括在这里面

要维护 \(\sum len[x]-len[fa[x]]\)

考虑插入一个结点会产生的贡献,因为每一条边只会贡献一次,所以需要容斥减掉一些贡献

那么需要考虑已经被加入的结点中与这个点 \(dfs\) 序相邻的,他们的 \(lca\) 以上的部分需要被减去

取与两个相邻节点的 \(lca\) 中深度较大的一个减去贡献,或者容斥一下

用 \(set\) 维护一下 \(dfs\) 序

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
char s[N];int cur=1,cnt=1,fa[N],len[N],ch[N][26],pos[N],FA[N][21],b[N],dep[N];
int n,st[N],tp=0,head[N],Head[N],nxt[N*4],to[N*4],num=0,la[N],dfn[N],DFN=0;
set<int>v;set<int>::iterator it,wt;
inline void link(int x,int y){nxt[++num]=head[x];to[num]=y;head[x]=num;}
inline void Link(int x,int y){nxt[++num]=Head[x];to[num]=y;Head[x]=num;}
inline void ins(int p,int c){
cur=++cnt;len[cur]=len[p]+1;
for(;p && !ch[p][c];p=fa[p])ch[p][c]=cur;
if(!p)fa[cur]=1;
else{
int q=ch[p][c];
if(len[p]+1==len[q])fa[cur]=q;
else{
int nt=++cnt;len[nt]=len[p]+1;
memcpy(ch[nt],ch[q],sizeof(ch[nt]));
fa[nt]=fa[q];fa[cur]=fa[q]=nt;
for(;p && ch[p][c]==q;p=fa[p])ch[p][c]=nt;
}
}
}
inline void bfs(){
queue<int>Q;
for(int i=head[0];i;i=nxt[i])Q.push(to[i]),la[to[i]]=1;
while(!Q.empty()){
int x=Q.front();Q.pop();
ins(la[x],s[x]-'a');pos[x]=cur;
for(int i=head[x];i;i=nxt[i])
Q.push(to[i]),la[to[i]]=cur;
}
}
inline void dfs(int x){
b[dfn[x]=++DFN]=x;
for(int i=1;i<=20;i++)FA[x][i]=FA[FA[x][i-1]][i-1];
for(int i=Head[x];i;i=nxt[i])dep[to[i]]=dep[x]+1,FA[to[i]][0]=x,dfs(to[i]);
}
inline int lca(int x,int y){
if(dep[x]<dep[y])swap(x,y);
int deep=dep[x]-dep[y];
for(int i=20;i>=0;i--)if(deep>>i&1)x=FA[x][i];
if(x==y)return x;
for(int i=20;i>=0;i--)if(FA[x][i]!=FA[y][i])x=FA[x][i],y=FA[y][i];
return FA[x][0];
}
ll ans=0;
inline void Modify(int x,int o){
if(o==1)v.insert(x);
it=wt=v.find(x);
ans+=o*len[b[x]];
if(wt!=v.begin())--wt,ans-=o*len[lca(b[*wt],b[x])];
if(it!=--v.end())++it,ans-=o*len[lca(b[*it],b[x])];
if(*it!=x && *wt!=x)ans+=o*len[lca(b[*it],b[*wt])];
if(o==-1)v.erase(x);
}
int main(){
freopen("C.in","r",stdin);
freopen("C.out","w",stdout);
scanf("%s",s+1);n=strlen(s+1);
for(int i=1;i<=n;i++){
if(s[i]=='-')tp--;
else link(st[tp],i),st[++tp]=i;
}
bfs();
for(int i=1;i<=cnt;i++)Link(fa[i],i);
dfs(1);tp=0;
for(int i=1;i<=n;i++){
if(s[i]=='-')Modify(dfn[pos[st[tp--]]],-1);
else Modify(dfn[pos[st[++tp]=i]],1);
printf("%lld\n",ans);
}
return 0;
}

bzoj 5084: hashit的更多相关文章

  1. BZOJ 5084: hashit 后缀自动机(原理题)

    比较考验对后缀自动机构建过程的理解. 之前看题解写的都是树链的并,但是想了想好像可以直接撤销,复杂度是线性的. 自己想出来的,感觉后缀自动机的题应该不太能难倒我~ 注意:一定要手画一下后缀自动机的构建 ...

  2. BZOJ 2127: happiness [最小割]

    2127: happiness Time Limit: 51 Sec  Memory Limit: 259 MBSubmit: 1815  Solved: 878[Submit][Status][Di ...

  3. BZOJ 3275: Number

    3275: Number Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 874  Solved: 371[Submit][Status][Discus ...

  4. BZOJ 2879: [Noi2012]美食节

    2879: [Noi2012]美食节 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1834  Solved: 969[Submit][Status] ...

  5. bzoj 4610 Ceiling Functi

    bzoj 4610 Ceiling Functi Description bzoj上的描述有问题 给出\(n\)个长度为\(k\)的数列,将每个数列构成一个二叉搜索树,问有多少颗形态不同的树. Inp ...

  6. BZOJ 题目整理

    bzoj 500题纪念 总结一发题目吧,挑几道题整理一下,(方便拖板子) 1039:每条线段与前一条线段之间的长度的比例和夹角不会因平移.旋转.放缩而改变,所以将每条轨迹改为比例和夹角的序列,复制一份 ...

  7. 【sdoi2013】森林 BZOJ 3123

    Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数.第三行包含N个非负整数 ...

  8. 【清华集训】楼房重建 BZOJ 2957

    Description 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子. 为了简化问题,我们考虑这些 ...

  9. 【splay】文艺平衡树 BZOJ 3223

    Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3  ...

随机推荐

  1. vs2015+opencv3.3.1 实现 c++ 灰度高斯滤波器

    #include <opencv2\highgui\highgui.hpp> #include <iostream> #include<vector> using ...

  2. 内联函数背景、例子、与普通函数的区别及要注意的地方 ------新标准c++程序设计

    背景: 使用函数能够避免将相同代码重些多次的烦恼,还能减少可执行程序的体积,但也会带来程序运行时间上的开销.函数调用在执行时,首先在栈中为形参和局部变量分配存储空间,然后还要将实参的值复制给形参,接下 ...

  3. jsonp的原理及其使用

    原理: 1.创建script标签 2.src远程地址 3.返回的数据必须为js格式 1.因为浏览器处于安全原因不允许跨域请求,但是允许跨域倒入js文件,所以需要创建script标签 2.src远程地址 ...

  4. mybatis 学习笔记(四):mybatis 和 spring 的整合

    mybatis 学习笔记(四):mybatis 和 spring 的整合 尝试一下整合 mybatis 和 spring. 思路 spring通过单例方式管理SqlSessionFactory. sp ...

  5. bzoj2564: 集合的面积(闵可夫斯基和 凸包)

    题面 传送门 题解 花了一个下午的时间调出了一个稍微能看的板子--没办法网上的板子和咱的不太兼容-- 首先有一个叫做闵可夫斯基和的东西,就是给你两个点集\(A,B\),要你求一个点集\(C=\{x+y ...

  6. mysql的时区错误问题,The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one

    在使用springboot整合ssm和druid的时候出现数据库一个问题 org.springframework.web.util.NestedServletException: Request pr ...

  7. python学习之路---day25( 网络编程基础和初识socket)

    基本网络知识和初识socket一:基本知识 网线:传输电信号 集线器:将所有连接到集线器的网络设备连通起来 交换机: 升级版的集线器 网卡:接受电信号 MAC地址:物理地址: 8C-88-4B-88- ...

  8. C++_类入门1-对象和类的介绍

    面向对象是(OOP)是特殊的.设计程序的概念性方法:包含以下特性: 抽象: 封装和数据隐藏: 多态: 继承: 代码的可重用性: 为了实现这些特性并且将这些特性组合在一起,C++所做的最重要的改进是提供 ...

  9. c#和java的深拷贝CloneObject

    public static T Clone<T>(this T source) { if (!typeof(T).IsSerializable) { throw new ArgumentE ...

  10. Apache Shiro(三)-登录认证和权限管理MD5加密

    md5 加密 在前面的例子里,用户密码是明文的,这样是有巨大风险的,一旦泄露,就不好了.所以,通常都会采用非对称加密,什么是非对称呢?就是不可逆的,而 md5 就是这样一个算法.如代码所示 123 用 ...