洛谷P2408 不同子串个数 后缀数组 + Height数组
## 题目描述:
给你一个长为 $N$ $(N<=10^5)$ 的字符串,求不同的子串的个数
我们定义两个子串不同,当且仅当有这两个子串长度不一样 或者长度一样且有任意一位不一样。子串的定义:原字符串中连续的一段字符组成的字符串
很妙的一道题,考察了对 $Height$ 数组的理解。
$1.$首先,不难发现任意子串都可以被字符串中后缀串的前缀表达出来
$2.$我们知道, $Height[i]$ 被定义为排名为 $i$ 的后缀串与排名为 $i-1$ 的后缀串的 $LCP$.
而与排名为 $i$ 得后缀串 $LCP$ 值最大的字符串必定是排名为 $i-1$ 的后缀串,他们的 $LCP$
值恰好就是 $Height$ 数组的值,即$Height[i]$.
考虑向后缀串集合中新加入一个后缀串 $sa[k]$, 共会产生 $n-sa[k]+1$ 个前缀串,但是有一些
前缀串在先前就已经会被计算到,会被计算到的前缀部分的最大值是 $Height[k]$,直接减去
$Height[k]$ 即可. 即贡献为 $n-sa[k]+1-Height[k]$.
Code:
#include <cstdio>
#include <algorithm>
#include <cstring>
#define setIO(s) freopen(s".in","r",stdin)
#define maxn 1000000
using namespace std;
char str[maxn];
int tr[maxn],rk[maxn],sa[maxn],arr[maxn],c[maxn],height[maxn];
int n,m;
struct Suffix_Array
{
void qsort()
{
for(int i=0;i<=m;++i) c[i]=0;
for(int i=1;i<=n;++i) ++c[rk[tr[i]]];
for(int i=1;i<=m;++i) c[i]+=c[i-1];
for(int i=n;i>=1;--i) sa[c[rk[tr[i]]]--]=tr[i];
}
void build()
{
for(int i=1;i<=n;++i) rk[i]=arr[i],tr[i]=i;
qsort();
for(int k=1;k<=n;k<<=1)
{
int num=0;
for(int i=n-k+1;i<=n;++i) tr[++num]=i;
for(int i=1;i<=n;++i) if(sa[i]>k) tr[++num]=sa[i]-k;
qsort();
swap(rk,tr);
rk[sa[1]]=1;
num=1;
for(int i=2;i<=n;++i)
rk[sa[i]]=(tr[sa[i]]==tr[sa[i-1]]&&tr[sa[i]+k]==tr[sa[i-1]+k])?num:++num;
if(num>=n) break;
m=num;
}
}
void get_height()
{
int k=0;
for(int i=1;i<=n;++i) rk[sa[i]]=i;
for(int i=1;i<=n;++i){
if(k) --k;
int j=sa[rk[i]-1];
while(arr[i+k]==arr[j+k]) ++k;
height[rk[i]]=k;
}
}
}T;
int main()
{
//setIO("input");
scanf("%d",&n);
scanf("%s",str),m=120;
for(int i=1;i<=n;++i) arr[i]=str[i-1]-'0';
T.build();
T.get_height();
long long ans=0;
for(int i=1;i<=n;++i)
ans+=(long long) (n-sa[i]+1-height[i]);
printf("%lld",ans);
return 0;
}
洛谷P2408 不同子串个数 后缀数组 + Height数组的更多相关文章
- [洛谷P2408]不同子串个数
题目大意:给你一个字符串,求其中本质不同的字串的个数 题解:同[洛谷P4070][SDOI2016]生成魔咒,只要最后再输出就行了 卡点:无 C++ Code: #include <cstdio ...
- 【文文殿下】洛谷P2408 不同子串个数
题目链接https://www.luogu.org/problemnew/show/P2408 SAM裸题,大力求就行了 #include<cstdio> #include<cstr ...
- LUOGU P2408 不同子串个数(后缀数组)
传送门 解题思路 后缀数组求本质不同串的裸题.\(ans=\dfrac{n(n+1)}{2} -\sum height[i]\). 代码 #include<iostream> #inclu ...
- [洛谷P3809]【模板】后缀排序
[洛谷P3809][模板]后缀排序 题目大意: 对于给定的长度为\(n(n\le10^6)\)的字符串求后缀数组\(sa[i]\). 思路: 倍增+快排构造后缀数组.代码参考<挑战程序设计竞赛& ...
- Luogu P2408 不同子串个数【SAM】
P2408 不同子串个数 计算一个字符串的不同子串个数 两种方法,一种是\(dp\)出来\(SAM\)从起点开始的路径数量 另一种方法就是计算每个点的\(len[i]-len[link[i]]\)这个 ...
- 洛谷P2408 不同字串个数 [后缀数组]
题目传送门 不同字串个数 题目背景 因为NOI被虐傻了,蒟蒻的YJQ准备来学习一下字符串,于是它碰到了这样一道题: 题目描述 给你一个长为N的字符串,求不同的子串的个数 我们定义两个子串不同,当且仅当 ...
- 【题解】洛谷P2679 [NOIP2015TG] 子串(DP+滚动数组)
次元传送门:洛谷P2679 思路 蒟蒻一开始并没有思路而去看了题解 我们发现对于两个字串的位置 我们只需要管他们匹配成功或者匹配失败即可 f[i][j][k] 记录当前 a[i]不论等不等于b[j] ...
- 洛谷P3763 [Tjoi2017]DNA 【后缀数组】
题目链接 洛谷P3763 题解 后缀数组裸题 在BZOJ被卡常到哭QAQ #include<algorithm> #include<iostream> #include< ...
- 洛谷P5069 [Ynoi2015]纵使日薄西山(树状数组,set)
洛谷题目传送门 一血祭 向dllxl致敬! 算是YNOI中比较清新的吧,毕竟代码只有1.25k. 首先我们对着题意模拟,寻找一些思路. 每次选了一个最大的数后,它和它周围两个数都要减一.这样无论如何, ...
随机推荐
- MongoDB数据修改案例
数据更新操作 队友MongoDB而言,数据更新是一件非常麻烦的事情.Mongo通常会存副本数据,数据有变更的时候,最好的做法是删除MongoDB的数据,重新插入. Mongo中提供了两个函数,一个是s ...
- linux 内存不足时候 应该及时回收page cache
另一起问题是24G内存的系统,空闲内存已经不到50M 1. 确认该系统的版本是64位 # uname -a Linux gxgd-nms-app 2.6.18-194.el5xen #1 SMP Tu ...
- VSCode向上的代码提示消除
VSCode虽然好用, 但是有些用户体验实在非常差, 比如这种往上面弹的类型提示... 在用户设置中增加: "editor.parameterHints": false
- Kettle和ETL的基本构成
不多说,直接上干货! 这里,我说的通俗易懂点,好方便大家的理解. ETL解决方案就像业务流程一样,具有输入.输出,以及一个或多个工作环节,处理步骤.同样的,这些步骤也具有输入和输出,并可以执行将一个输 ...
- js调节图片的亮度
js调节图片的亮度:(使用CSS3的滤镜) 1.实现点亮图标.熄灭图标的效果 效果图: 页面代码: <!DOCTYPE html> <%@ page language="j ...
- POJ 1852 Ants O(n)
题目: 思路:蚂蚁相碰和不相碰的情况是一样的,相当于交换位置继续走. 代码: #include <iostream> #include <cstdio> #include &l ...
- HTML&CSS——使用DIV和CSS完成网站首页重构
1.DIV 相关的技术 Div 它是一个 html 标签,一个块级元素(单独显示一行).它单独使用没有任何意义,必须结合CSS来使用.它主要用于页面的布局. Span 它是一个 html 标签,一个内 ...
- Html标记语言学习一2017年6月12日
今天主要学习了 frame的用法. <frameset> 可以将网页分成几个不同的部分 使用 cols 和 rows 两种标记.前者是列,后者是行 <frame/> 单标 ...
- pycharm日常填坑
pycharm坑很多,今天又遇见了,好吧 ,填坑 场景:从别的地方拷贝过来的项目,导入本地的pycharm 然后选择 然后 还会报错....心累 报错内容: django commands canno ...
- 【BZOJ4016】【FJOI2014】最短路径树问题
题意: Description 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径走.若有多条长度最短的路径,则选择经过的顶点序列 ...