题目传送门

不同字串个数

题目背景

因为NOI被虐傻了,蒟蒻的YJQ准备来学习一下字符串,于是它碰到了这样一道题:

题目描述

给你一个长为N的字符串,求不同的子串的个数

我们定义两个子串不同,当且仅当有这两个子串长度不一样 或者长度一样且有任意一位不一样。

子串的定义:原字符串中连续的一段字符组成的字符串

输入输出格式

输入格式:

第一行一个整数N

接下来一行N个字符表示给出的字符串

输出格式:

一行一个整数,表示不一样的子串个数

输入输出样例

输入样例#1:

5
aabaa
输出样例#1:

11
输入样例#2:

3
aba
输出样例#2:

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 不同字串个数 [后缀数组]的更多相关文章

  1. 洛谷2408不同字串个数/SPOJ 694/705 (后缀数组SA)

    真是一个三倍经验好题啊. 我们来观察这个题目,首先如果直接整体计算,怕是不太好计算. 首先,我们可以将每个子串都看成一个后缀的的前缀.那我们就可以考虑一个一个后缀来计算了. 为了方便起见,我们选择按照 ...

  2. 【题解】洛谷P1032 [NOIP2002TG]字串变换(BFS+字符串)

    洛谷P1032:https://www.luogu.org/problemnew/show/P1032 思路 初看题目觉得挺简单的一道题 但是仔细想了一下发现实现代码挺麻烦的 而且2002年的毒瘤输入 ...

  3. 【洛谷】P1032 字串变换

    题目地址:https://www.luogu.org/problemnew/show/P1032 洛谷训练场BFS的训练题呀. “BFS不就是用队列的思想去遍历一切情况嘛.我已经不是小孩子了,我肯定能 ...

  4. 洛谷 P1032 【字串变换】

    感觉这个题用一些常用的stl和string函数会非常简单..(难道就是考这两个的吗? vector<pair<string,string>>pos//用于变化 map<s ...

  5. 洛谷P2178 [NOI2015]品酒大会 后缀数组+单调栈

    P2178 [NOI2015]品酒大会 题目链接 https://www.luogu.org/problemnew/show/P2178 题目描述 一年一度的"幻影阁夏日品酒大会" ...

  6. 洛谷P4493 [HAOI2018]字串覆盖(后缀自动机+线段树+倍增)

    题面 传送门 题解 字符串就硬是要和数据结构结合在一起么--\(loj\)上\(rk1\)好像码了\(10k\)的样子-- 我们设\(L=r-l+1\) 首先可以发现对于\(T\)串一定是从左到右,能 ...

  7. 【洛谷 P2408】 不同子串个数(后缀自动机)

    题目链接 裸体就是身体. 建出\(SAM\),\(DAG\)上跑\(DP\),\(f[u]=1+\sum_{(u,v)\in DAG}f[v]\) 答案为\(f[1]-1\)(因为根节点没有字符) # ...

  8. 【洛谷P3411】字串变换

    题解:普通的 BFS 没什么可说的,字符串处理是这道题的难点,同时需要注意哈希判重. 另外,对于 \(string\) 类来说,学到了一个 push_back((char)) 操作. c++strin ...

  9. [洛谷P1279][题解]字串距离

    题目戳我 很明显的这题是一道dp,主要讲一下几个细节 1.初始化 我们需要初始化边界情况也就是一个字符串为空的情况 #----------# #----------# A:aaaaaa A:□□□□□ ...

随机推荐

  1. C++标准库头文件找不到的问题

    当你写C++程序时,在头文件中包含C++标准库的头文件,比如#include <string>,而编译器提示你找不到头文件! 原因就是你的实现源文件扩展名是".c"而不 ...

  2. fmt:formatNumber use locale display negative currency in -$xxx.xx format in JSTL

    First, we want to know our own locale,how to display the locale in a JSTL? <c:out value="${p ...

  3. Spring整合JMS(二)——三种消息监听器(转)

    *注:别人那复制来的 1.3     消息监听器MessageListener 在Spring整合JMS的应用中我们在定义消息监听器的时候一共可以定义三种类型的消息监听器,分别是MessageList ...

  4. c# WebService SOAP及Rest调用

    SOAP及Rest的调用区别参照如下: REST似乎在一夜间兴起了,这可能引起一些争议,反对者可以说REST是WEB诞生之始甚而是HTTP出现之日就相伴而生的原则.但是毋庸置疑的事实是,在Google ...

  5. IDEA 启动时,报“淇℃伅”的字符

    IDEA 启动时,报“淇℃伅”的字符,如下: 解决办法: 修改tomcat安装目录下的config/logging.properties文件,找到java.util.logging.ConsoleHa ...

  6. 【CODEVS】1022 覆盖

    [算法]二分图匹配(最大流) [题解]对i+j进行奇偶染色,就可以保证相邻两格异色. 然后就是二分图了,对相邻格子连边跑最大流即可. #include<cstdio> #include&l ...

  7. 回溯算法_01背包问题_Java实现

    原文地址:http://blog.csdn.net/ljmingcom304/article/details/50314839 本文出自:[梁敬明的博客] 1.回溯算法 回溯算法也叫试探法,通俗的将就 ...

  8. SQLite3使用详解

    sqlite常量的定义(SQLite3返回值的意思): SQLITE_OK           = 0;  返回成功 SQLITE_ERROR        = 1;  SQL错误或错误的数据库 SQ ...

  9. 008 BlockingQueue理解

    原文https://www.cnblogs.com/WangHaiMing/p/8798709.html 本篇将详细介绍BlockingQueue,以下是涉及的主要内容: BlockingQueue的 ...

  10. js事件、事件委托

    事件流 事件流:页面中接收事件的顺序: IE的事件流是冒泡流,其他的浏览器是捕获流,如下图: DOM事件流 DOM 事件流同时支持这两种事件流,并且规定DOM任何事件流都包含三个阶段:事件捕获阶段.处 ...