洛谷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:□□□□□ ...
随机推荐
- C++ string的那些坑
1. size_type find_first_of( const basic_string &str, size_type index = 0 ); 查找在字符串中第一个与str中的某个字符 ...
- php 傻瓜式代码计算两个时间间隔
$stamp = (strtotime($_POST['start'])-strtotime($_POST['end'])); $s = $stamp%60; //秒 $m_stamp= ($stam ...
- jQuery常用插件大全
1.五星级插件jRating 详细文档介绍:http://www.myjqueryplugins.com/jquery-plugin/jrating 2.图片展示插件Swiper和Slider swi ...
- NOIP模拟赛11
T1 [HAOI2016]放棋子 https://daniu.luogu.org/problem/show?pid=3182 障碍交换行不影响 所以第i列有障碍的行换到第i行 然后错排公式 本校自测要 ...
- JAVA多线程提高十二:阻塞队列应用
一.类相关属性 接口BlockingQueue<E>定义: public interface BlockingQueue<E> extends Queue<E> { ...
- 【CodeForces】704 B. Ant Man
[题目]B. Ant Man [题意]给定n个人的xi,ai,bi,ci,di,起点为s,终点为e,移动: In simpler words, jumping from i-th chair to j ...
- 一个python爬虫工具类
写了一个爬虫工具类. # -*- coding: utf-8 -*- # @Time : 2018/8/7 16:29 # @Author : cxa # @File : utils.py # @So ...
- 读书笔记 effective c++ Item 4 确保对象被使用前进行初始化
C++在对象的初始化上是变化无常的,例如看下面的例子: int x; 在一些上下文中,x保证会被初始化成0,在其他一些情况下却不能够保证.看下面的例子: class Point { int x,y; ...
- centos7安装完成后的一些配置
1.打开终端 输入 sudo yum -y update 先更新软件包 2.这是输入语言 应用程序->系统工具->设置->区域和语言->+ ->汉语(中国)-> ...
- ASP.NET Core 2.0 MVC 发布部署--------- linux安装.NET CORE SDK具体操作链接以及操作总细节
具体链接:https://www.microsoft.com/net/learn/get-started/linuxubuntu 如下图: