洛谷P2408 不同字串个数 [后缀数组]
不同字串个数
题目背景
因为NOI被虐傻了,蒟蒻的YJQ准备来学习一下字符串,于是它碰到了这样一道题:
题目描述
给你一个长为N的字符串,求不同的子串的个数
我们定义两个子串不同,当且仅当有这两个子串长度不一样 或者长度一样且有任意一位不一样。
子串的定义:原字符串中连续的一段字符组成的字符串
输入输出格式
输入格式:
第一行一个整数N
接下来一行N个字符表示给出的字符串
输出格式:
一行一个整数,表示不一样的子串个数
输入输出样例
5
aabaa
11
3
aba
5
说明
请使用64位整数来进行输出
(具体来说,C++和C选手请使用long long 类型,pascal选手请使用Int64)
由于输入文件过大,请使用 高效的读入方法(具体的,c++和c选手请不要使用cin,pascal选手不需要管)
对于30%的数据, $N\le 1000$
对于100%的数据, $N\le 10^5$
分析:
后缀数组入门好题,刚学,特地来水一波。
首先做这道题需要会后缀数组,并深入理解$height[]$数组的含义,然后需要知道一个非常重要的性质。下面这一段话引用自罗穗骞的论文:
每个子串一定是某个后缀的前缀,那么原问题等价于求所有后缀之间的不相同的前缀的个数。如果所有的后缀按照 suffix(sa[1]), suffix(sa[2]),suffix(sa[3]), …… ,suffix(sa[n])的顺序计算,不难发现,对于每一次新加进来的后缀 suffix(sa[k]),它将产生 n-sa[k]+1 个新的前缀。但是其中有height[k]个是和前面的字符串的前缀是相同的。所以 suffix(sa[k])将“贡献”出 n-sa[k]+1- height[k]个不同的子串。累加后便是原问题的答案。这个做法的时间复杂度为 O(n)。
知道这些这道题就可以轻松A过了。
Code:
//It is made by HolseLee on 13th Aug 2018
//Luogu.org P2408
#include<bits/stdc++.h>
using namespace std; typedef long long ll;
const int N=1e5+;
int n,m,height[N],sa[N],rk[N],y[N],c[N];
ll ans;
char s[N]; void Sort()
{
for(int i=;i<=m;++i)c[i]=;
for(int i=;i<=n;++i)c[rk[i]]++;
for(int i=;i<=m;++i)c[i]+=c[i-];
for(int i=n;i>=;--i)sa[c[rk[y[i]]]--]=y[i];
} void getsa()
{
for(int i=;i<=n;++i)rk[i]=s[i]-'',y[i]=i;
Sort();
for(int k=,cnt=;cnt<n;m=cnt,k<<=){
cnt=;
for(int i=;i<=k;++i)y[++cnt]=n-k+i;
for(int i=;i<=n;++i)if(sa[i]>k)y[++cnt]=sa[i]-k;
Sort();
swap(y,rk);
rk[sa[]]=cnt=;
for(int i=;i<=n;++i)
rk[sa[i]]=(y[sa[i]]==y[sa[i-]]&&y[sa[i]+k]==y[sa[i-]+k])?cnt:++cnt;
}
} void getheight()
{
int k=,j;
for(int i=;i<=n;++i){
if(k)k--;
j=sa[rk[i]-];
while(s[i+k]==s[j+k])k++;
height[i]=k;
}
} int main()
{
scanf("%d%s",&n,s+);
m=;
getsa();getheight();
for(int i=;i<=n;++i)
ans+=(n-sa[i]+-height[i]);
printf("%lld",ans);
return ;
}
洛谷P2408 不同字串个数 [后缀数组]的更多相关文章
- 洛谷2408不同字串个数/SPOJ 694/705 (后缀数组SA)
真是一个三倍经验好题啊. 我们来观察这个题目,首先如果直接整体计算,怕是不太好计算. 首先,我们可以将每个子串都看成一个后缀的的前缀.那我们就可以考虑一个一个后缀来计算了. 为了方便起见,我们选择按照 ...
- 【题解】洛谷P1032 [NOIP2002TG]字串变换(BFS+字符串)
洛谷P1032:https://www.luogu.org/problemnew/show/P1032 思路 初看题目觉得挺简单的一道题 但是仔细想了一下发现实现代码挺麻烦的 而且2002年的毒瘤输入 ...
- 【洛谷】P1032 字串变换
题目地址:https://www.luogu.org/problemnew/show/P1032 洛谷训练场BFS的训练题呀. “BFS不就是用队列的思想去遍历一切情况嘛.我已经不是小孩子了,我肯定能 ...
- 洛谷 P1032 【字串变换】
感觉这个题用一些常用的stl和string函数会非常简单..(难道就是考这两个的吗? vector<pair<string,string>>pos//用于变化 map<s ...
- 洛谷P2178 [NOI2015]品酒大会 后缀数组+单调栈
P2178 [NOI2015]品酒大会 题目链接 https://www.luogu.org/problemnew/show/P2178 题目描述 一年一度的"幻影阁夏日品酒大会" ...
- 洛谷P4493 [HAOI2018]字串覆盖(后缀自动机+线段树+倍增)
题面 传送门 题解 字符串就硬是要和数据结构结合在一起么--\(loj\)上\(rk1\)好像码了\(10k\)的样子-- 我们设\(L=r-l+1\) 首先可以发现对于\(T\)串一定是从左到右,能 ...
- 【洛谷 P2408】 不同子串个数(后缀自动机)
题目链接 裸体就是身体. 建出\(SAM\),\(DAG\)上跑\(DP\),\(f[u]=1+\sum_{(u,v)\in DAG}f[v]\) 答案为\(f[1]-1\)(因为根节点没有字符) # ...
- 【洛谷P3411】字串变换
题解:普通的 BFS 没什么可说的,字符串处理是这道题的难点,同时需要注意哈希判重. 另外,对于 \(string\) 类来说,学到了一个 push_back((char)) 操作. c++strin ...
- [洛谷P1279][题解]字串距离
题目戳我 很明显的这题是一道dp,主要讲一下几个细节 1.初始化 我们需要初始化边界情况也就是一个字符串为空的情况 #----------# #----------# A:aaaaaa A:□□□□□ ...
随机推荐
- SQL基础操作
SQL是操作数据的语言 增加记录: insert into 数据表名称(字段1,字段2,字段3....)values(值1,值2,值3.....) 查看表结构:desc 表名 inset into x ...
- NOIP 2015 提高组 Day2
期望得分:100+10+60=170 实际得分:100+10+35=145 http://www.cogs.pro/cogs/page/page.php?aid=16 T1 跳石头 时间限制:1 s ...
- ⑤ 设计模式的艺术-05.原型(Prototype)模式
场景 思考一下:克隆技术是怎么样的过程? 克隆羊多利大家还记得吗? javascript语言中的,继承怎么实现?那里面也有prototype,大家还记得吗? 原型模式 通过new产生一个对象需要非常繁 ...
- 【BZOJ】4129: Haruna’s Breakfast 树分块+带修改莫队算法
[题意]给定n个节点的树,每个节点有一个数字ai,m次操作:修改一个节点的数字,或询问一条树链的数字集合的mex值.n,m<=5*10^4,0<=ai<=10^9. [算法]树分块+ ...
- 使用Skyworking 作全链路api调用监控,Integration of Skyworking, auditing the whole chain circuit.
Applicable scenario: Structure Map ~ Skywalking uses elasticsearch to store data, don't mistake elas ...
- 小程序 mcrypt加密拓展在php7.1 废弃 使用openssl替代方案
原加密方法 使用mcrypt //获得16位随机字符串,填充到明文之前 $random = $this->getRandomStr(); $text = $random . pack(" ...
- 飘雪效果的swf
//第一帧动作 import flash.events.Event; ;k<;k++) { var xuehua:xue= new xue(); xuehua.alpha = Math.rand ...
- linux的主题与图标
我先在使用arch跟xfce, 速度没得说,偶尔用一下openbox 有一天将xfce的声音给搞没了,完全不知道哪里配置错了,只好将用户文件夹下的所有配置删除,然后重启进入一切又ok啦 说一下主题,小 ...
- python基础之常用的高阶函数
前言 高阶函数指的是能接收函数作为参数的函数或类:python中有一些内置的高阶函数,在某些场合使用可以提高代码的效率. map() map函数可以把一个迭代对象转换成另一个可迭代对象,不过在pyth ...
- SPI最大传输速率【转】
转自:https://www.silabs.com/community/mcu/8-bit/knowledge-base.entry.html/2017/01/13/spi_-asc0 问题 SPI作 ...