洛谷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. 首先我们对着题意模拟,寻找一些思路. 每次选了一个最大的数后,它和它周围两个数都要减一.这样无论如何, ...
随机推荐
- 143.vector模板库
myvector.h #pragma once #include <initializer_list> #include <iostream> using namespace ...
- 计算label
func getCGSize(size:CGSize,fontSize:CGFloat,text:String)->CGSize{ let attributes = [NSFontAttribu ...
- Hadoop编译源码
Hadoop编译源码 克隆一个虚拟机 然后一步一步安装就行 安装所需:链接: https://pan.baidu.com/s/1jIZlQmi 密码: gggv 5.1 前期准备工作 1)CentOS ...
- Java中如何解决线程安全问题
给出一个问题,如下: 解决方案如下: public class Demo_5 { public static void main(String[] args) { //创建一个窗口 TicketWin ...
- QT笔记 -- (4) 为QLabel添加鼠标响应方法2
1.实现 bool eventFilter(QObject *target,QEvent *event) 函数内容如下: bool eventFilter(QObject *target,QEvent ...
- php xml 的基本操作类
class xmlMessage{ protected $doc; protected $rootKey; public function __construct() { $this->doc ...
- Promise语法
转自:廖雪峰的官方网站 在JavaScript的世界中,所有代码都是单线程执行的. 由于这个“缺陷”,导致JavaScript的所有网络操作,浏览器事件,都必须是异步执行.异步执行可以用回调函数实现: ...
- axios使用方法
npm install axios 创建文件夹api/index.js import axios from 'axios'; let http = axios.create({ baseURL: '' ...
- Linux 操作基础(一) -- Shell 命令格式和元字符
1 命令格式 cmd [-选项] [参数] 说明: • 最简单的Shell命令只有命令名,复杂的Shell命令可以有多个选项和参数 • 参数是文件也可以是目录,有些命令必须使用多个操作对象 • 并非所 ...
- MySQL 数据还原
1.1还原使用mysqldump命令备份的数据库的语法如下: mysql -u root -p [dbname] < backup.sq 示例: mysql -u root -p < C: ...