题意:一个串初始为空,n次像串尾添加元素,每次添加后回答本质不同的子串个数

n<=1e5 字符集大小1e9

Sol:

本质不同的子串个数,考虑后缀数据结构

发现向结尾添加字符对后缀数组不友好,但是在开头添加很资瓷,相当于新添加一个后缀

于是考虑离线,把最终串搞出来在翻转一下,建立后缀数组,问题转化成动态添加后缀求不同子串个数

每次找到当前后缀应在位置,去掉后缀对前驱的影响,加上后继与前驱对她的影响,递推即可

找后缀可以用set

也可以再将这个过程逆转,每次删除后缀,这样可以用双线链表找前驱后继

算影响用正常的RMQ算法

因为字符集大需要先离散化

总复杂度O(nlogn)

好麻烦啊。。。年轻人,你听说过后缀自动机吗

会后缀自动机后发现这是一道裸题,字符集大?map一发

总复杂度也是O(nlogn) 还是在线的,比后缀数组高到不知道哪里去了

科技是第一生产力啊2333

Code:

后缀数组

//Suffix_Array - 528ms
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100009, Log = 18;int c[maxn],t[maxn],t2[maxn],sa[maxn],rank[maxn],height[maxn];
int s[maxn],b[maxn],ft[maxn],nxt[maxn],pre[maxn];
int n;
long long ans[maxn];
struct ST
{int mn[Log+1][maxn];void build(int *a){for(int i=1;i<=n;i++) mn[0][i]=a[i];for(int i=1;i<=Log;i++)for(int j=1;j<=n-(1<<i)+1;j++)mn[i][j]=min(mn[i-1][j],mn[i-1][j+(1<<i>>1)]);}int query(int l,int r){int len=ft[r-l+1];return min(mn[len][l],mn[len][r-(1<<len)+1]);}
}H;inline int read()
{int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;
}
int find(int x)
{int l=1,r=b[0];while(l<=r){int mid=(l+r)>>1;if(b[mid]==x) return mid;if(b[mid]<x) l=mid+1;else r=mid-1;}
}void build()
{int mr=b[0],*x=t,*y=t2;for(int i=1;i<=mr;i++) c[i]=0;for(int i=1;i<=n;i++) c[x[i]=s[i]]++;for(int i=1;i<=mr;i++) c[i]+=c[i-1];for(int i=n;i>=1;i--) sa[c[x[i]]--]=i;for(int k=1;k<=n;k<<=1){int p=0;for(int i=n-k+1;i<=n;i++) y[++p]=i;for(int i=1;i<=n;i++) if(sa[i]>k) y[++p]=sa[i]-k;for(int i=1;i<=mr;i++) c[i]=0;for(int i=1;i<=n;i++) c[x[y[i]]]++;for(int i=1;i<=mr;i++) c[i]+=c[i-1];for(int i=n;i>=1;i--) sa[c[x[y[i]]]--]=y[i];swap(x,y);p=1;x[sa[1]]=1;for(int i=2;i<=n;i++)if(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]) x[sa[i]]=p;else x[sa[i]]=++p;if(p>=n) break;mr=p;}for(int i=1;i<=n;i++) rank[sa[i]]=i;int h=0;for(int i=1;i<=n;i++){if(rank[i]==1) h=0;else{int k=sa[rank[i]-1];h--;if(h<0) h=0;while(s[k+h]==s[i+h]) h++;}height[rank[i]]=h;}H.build(height);for(int i=1;(1<<i)<=n;i++) ft[1<<i]=i;for(int i=1;i<=n;i++) if(!ft[i]) ft[i]=ft[i-1];for(int i=1;i<=n;i++) nxt[i]=i+1,pre[i]=i-1;nxt[n]=pre[1]=0;}int lcp(int x,int y){return H.query(x+1,y);}void erase(int x)
{nxt[pre[x]]=nxt[x];pre[nxt[x]]=pre[x];nxt[x]=pre[x]=0;
}int main()
{n=read();for(int i=1;i<=n;i++) b[i]=s[i]=read();sort(b+1,b+1+n);b[0]=unique(b+1,b+1+n)-b-1;for(int i=1;i<=n;i++) s[i]=find(s[i]);reverse(s+1,s+1+n);build();for(int i=2;i<=n;i++) ans[1]-=height[i];for(int i=2;i<=n;i++){ans[i]=ans[i-1];int x=rank[i-1],l=pre[x],r=nxt[x];if(l) ans[i]+=lcp(l,x);if(r) ans[i]+=lcp(x,r);if(l&&r) ans[i]-=lcp(l,r);erase(x);}for(int i=n;i>=1;i--) ans[n-i+1]+=1ll*(i+1)*i/2;for(int i=n;i>=1;i--) printf("%lld\n",ans[i]);return 0;
}

后缀自动机

//Suffix_Automaton - 764ms
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100009;struct SAM
{int tot,last,root;long long ans;struct state{map<int,int>son;int mx,par;}node[maxn<<1];int calc(int x){if(x==root) return 0;return node[x].mx-node[node[x].par].mx;}void init(){tot=last=root=1;}void extend(int x){int p=last,np=++tot;node[np].mx=node[p].mx+1;while(p&&node[p].son[x]==0)node[p].son[x]=np,p=node[p].par;if(p==0){node[np].par=root;ans+=calc(np);}else{int q=node[p].son[x];if(node[p].mx+1==node[q].mx){node[np].par=q;ans+=calc(np);}else{int nq=++tot;node[nq].son=node[q].son;node[nq].mx=node[p].mx+1;ans-=calc(q);node[nq].par=node[q].par;node[np].par=node[q].par=nq;ans+=calc(np)+calc(nq)+calc(q);while(p&&node[p].son[x]==q)node[p].son[x]=nq,p=node[p].par;}}last=np;}
}uuz;
int n;inline int read()
{int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;
}int main()
{n=read();uuz.init();for(int i=1;i<=n;i++){int x=read();uuz.extend(x);printf("%lld\n",uuz.ans);}return 0;
}

BZOJ4516 [Sdoi2016]生成魔咒 后缀自动机/后缀数组相关推荐

  1. BZOJ4516: [Sdoi2016]生成魔咒

    BZOJ4516: [Sdoi2016]生成魔咒 Description 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示. 例如可以将魔咒字符 1.2 拼凑起来形成一个魔咒串 [1,2]. 一个魔咒 ...

  2. P4070 [SDOI2016]生成魔咒(SAM len数组的含义)

    [SDOI2016]生成魔咒 题目描述 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示.例如可以将魔咒字符 1 , 2 1,2 1,2 拼凑起来形成一个魔咒串 [ 1 , 2 ] [1,2] [1, ...

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

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

  4. bzoj4516 / P4070 [SDOI2016]生成魔咒

    P4070 [SDOI2016]生成魔咒 后缀自动机 每插入一个字符,对答案的贡献为$len[last]-len[fa[last]]$ 插入字符范围过大,所以使用$map$存储. (去掉第35行就是裸 ...

  5. [SDOI2016]生成魔咒

    4516: [Sdoi2016]生成魔咒 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 1460  Solved: 835 [Submit][Sta ...

  6. P4070 [SDOI2016]生成魔咒

    P4070 [SDOI2016]生成魔咒 题意: 有n个字符xi,每次在S的末尾加入一个字符,(一开始S为空),每次加入xi后的不相同字串有多少个 题解: 做这个题首先要会后缀数组P3809 [模板] ...

  7. 洛谷 P4070 [SDOI2016]生成魔咒 解题报告

    P4070 [SDOI2016]生成魔咒 题目描述 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示.例如可以将魔咒字符 \(1\).\(2\) 拼凑起来形成一个魔咒串 \([1,2]\). 一个魔咒 ...

  8. 洛谷 P4070 [SDOI2016]生成魔咒 后缀自动机

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

  9. [SDOI2016] 生成魔咒(后缀数组SA + st表 + set)动态不同子串个数

    problem luogu-P4070 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示.例如可以将魔咒字符 1,21,21,2 拼凑起来形成一个魔咒串 [1,2][1,2][1,2]. 一个魔咒串 ...

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

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

最新文章

  1. fb静态区域_fb 静态数据
  2. 计算机英语讲课笔记03
  3. 计算机三级网络技术综合题解析,计算机三级网络技术上机考试习题答案及解析...
  4. pandas —— pd.read_csv 与df.to_csv
  5. 【Django 2021年最新版教程6】前端传递数据到后端处理 POST方法
  6. ckeditor+ckfinder使用
  7. 所谓的三十之后无技术
  8. c1200 写频软件_金飞讯写频软件-金飞讯a66写频软件(金飞讯a66对讲机写频软件)1.0 一键安装版-东坡下载...
  9. 华为是不是培养人工智能人才花费最大的公司?
  10. 通过Java 画一个太极图
  11. 解决margin坍塌
  12. 《荔枝架构实践与演进历程》阅读有感
  13. Mono.Cecil
  14. 微信小程序转码机器人----【在线实战】
  15. 新时达电梯服务器维修,常见的新时达电梯维修时问题分析
  16. 柔性作业车间调度问题 (FJSSP)
  17. 深入浅出工控机加固的那点事
  18. Unity3D命令手册
  19. 基于Socket的五子棋游戏
  20. 收藏,Python 开发中有哪些高级技巧?

热门文章

  1. 由“外”向“内”,安踏破解运动科技“卡脖子”难题
  2. 三 国外IP核主要竞争对手
  3. 怎么制作QQ背景音乐链接
  4. 元学习 - Learning How to Learn - 第一课:集中与发散思维
  5. 腾达路由器显示远程服务器无响应,腾达路由器设置及可能出现的问题
  6. U-net复现pytorch版本 以及制作自己的数据集并训练
  7. 计算机考试网页制作演示视频教程,一级计算机考试网页制作怎么办!求操作步骤!...
  8. (翻译)社会认同模式(Social proof)
  9. CS5218: DP转HDMI 4K30HZ转换方案
  10. 立此存照:杨振宁 VS 邓稼先 (转贴)