## 题目描述:

给你一个长为 $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数组的更多相关文章

  1. [洛谷P2408]不同子串个数

    题目大意:给你一个字符串,求其中本质不同的字串的个数 题解:同[洛谷P4070][SDOI2016]生成魔咒,只要最后再输出就行了 卡点:无 C++ Code: #include <cstdio ...

  2. 【文文殿下】洛谷P2408 不同子串个数

    题目链接https://www.luogu.org/problemnew/show/P2408 SAM裸题,大力求就行了 #include<cstdio> #include<cstr ...

  3. LUOGU P2408 不同子串个数(后缀数组)

    传送门 解题思路 后缀数组求本质不同串的裸题.\(ans=\dfrac{n(n+1)}{2} -\sum height[i]\). 代码 #include<iostream> #inclu ...

  4. [洛谷P3809]【模板】后缀排序

    [洛谷P3809][模板]后缀排序 题目大意: 对于给定的长度为\(n(n\le10^6)\)的字符串求后缀数组\(sa[i]\). 思路: 倍增+快排构造后缀数组.代码参考<挑战程序设计竞赛& ...

  5. Luogu P2408 不同子串个数【SAM】

    P2408 不同子串个数 计算一个字符串的不同子串个数 两种方法,一种是\(dp\)出来\(SAM\)从起点开始的路径数量 另一种方法就是计算每个点的\(len[i]-len[link[i]]\)这个 ...

  6. 洛谷P2408 不同字串个数 [后缀数组]

    题目传送门 不同字串个数 题目背景 因为NOI被虐傻了,蒟蒻的YJQ准备来学习一下字符串,于是它碰到了这样一道题: 题目描述 给你一个长为N的字符串,求不同的子串的个数 我们定义两个子串不同,当且仅当 ...

  7. 【题解】洛谷P2679 [NOIP2015TG] 子串(DP+滚动数组)

    次元传送门:洛谷P2679 思路 蒟蒻一开始并没有思路而去看了题解 我们发现对于两个字串的位置 我们只需要管他们匹配成功或者匹配失败即可 f[i][j][k] 记录当前 a[i]不论等不等于b[j] ...

  8. 洛谷P3763 [Tjoi2017]DNA 【后缀数组】

    题目链接 洛谷P3763 题解 后缀数组裸题 在BZOJ被卡常到哭QAQ #include<algorithm> #include<iostream> #include< ...

  9. 洛谷P5069 [Ynoi2015]纵使日薄西山(树状数组,set)

    洛谷题目传送门 一血祭 向dllxl致敬! 算是YNOI中比较清新的吧,毕竟代码只有1.25k. 首先我们对着题意模拟,寻找一些思路. 每次选了一个最大的数后,它和它周围两个数都要减一.这样无论如何, ...

随机推荐

  1. nyoj--203--三国志(迪杰斯特拉+背包)

    三国志 时间限制:3000 ms  |  内存限制:65535 KB 难度:5 描述 <三国志>是一款很经典的经营策略类游戏.我们的小白同学是这款游戏的忠实玩家.现在他把游戏简化一下,地图 ...

  2. BZOJ 3175 最大独立集

    思路: 最大独立集嘛 用nlogn的Dinic做 //By SiriusRen #include <queue> #include <cstdio> #include < ...

  3. flex布局下img变形的问题

    flex-shrink  加上:flex-shrink:0:定义了缩小比例,默认为1,即如果空间不足,项目将会缩小所有项目为1时,空间不足,都会缩小,如果你不希望某个容器在任何时候都不被压缩,那设置f ...

  4. WPF学习(四) - 附加属性

    冷静了一晚,我就当这次学习的过程是在看狗血剧情的武打小说吧:没有垃圾的武术,只有垃圾的武者…… 还有个话儿怎么说来着:你们是用户,不是客户,也就有个使用的权力.搞清楚身份,别叽叽歪歪的! 没办法,全世 ...

  5. APICloud关闭Key Building Resolve

    顶部菜单 --> 扩展 --> keybinding resolver --> toggle

  6. Android 设计一个菱形形状的Imageview组件.

    网上没有资料,特来请教下大神 Android 设计一个菱形形状的Imageview组件. >> android这个答案描述的挺清楚的:http://www.goodpm.net/postr ...

  7. 之前的大数相加存在bug,这个ac通过了

    #include <iostream> #include <string> /*project:两个大整数相加 **@author:浅滩 **data:2019.05.15 * ...

  8. LaTex的几种数学符号字体以及相关说明

    \mathrm is the normal upright Roman font \mathnormal is the normal math italic font: $\mathnormal{a} ...

  9. 拉格朗日插值&&快速插值

    拉格朗日插值 插值真惨 众所周知$k+1$个点可以确定一个$k$次多项式,那么插值就是通过点值还原多项式的过程. 设给出的$k+1$个点分别是$(x_0,y_0),(x_1,y_1),...,(x_k ...

  10. java用freemarker实现导出word----包含图片

    分为以下三个步骤: 1.先制作word模板 2.将该文档另存为 xml 文件 3.打开xml 文件 将对应的字段替换,比如 4.将xml文件保存成ftl格式的文档 5.相应的代码: package o ...