SPOJ Distinct Substrings【后缀数组】
Given a string, we need to find the total number of its distinct substrings.
Input
T- number of test cases. T<=20;
Each test case consists of one string, whose length is <= 1000
Output
For each test case output one number saying the number of distinct substrings.
Example
Sample Input:
2
CCCCC
ABABA
Sample Output:
5
9
Explanation for the testcase with string ABABA:
len=1 : A,B
len=2 : AB,BA
len=3 : ABA,BAB
len=4 : ABAB,BABA
len=5 : ABABA
Thus, total number of distinct substrings is 9.
题意:
求一个字符串中所有的不相同的子串个数。
思路:
一个字符串的所有子串个数是n*(n+1)/2,关键就是有多少是重复的。
一个子串其实就是原字符串某个后缀的前缀,找到有多少重复的其实就是找后缀的lcp
比如我们遍历到了第k个后缀,本来他可以产生len个前缀,但是他的前面有一部分前缀是已经算过的了。
而且由于 LCP(i,j)=min{LCP(k-1,k)|i+1≤k≤j} ,且对 i≤j<k,LCP(j,k)≥LCP(i,k)
每加入一个后缀,应该减去max(LCP(i,j)), 也就是LCP(i-1,i),也就是height[i]
#include <iostream>
#include <set>
#include <cmath>
#include <stdio.h>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
using namespace std;
typedef long long LL;
#define inf 0x7f7f7f7f const int maxn = ;
int t;
char str[maxn]; int sa[maxn];
int t1[maxn], t2[maxn], c[maxn];
int rnk[maxn], height[maxn]; void build_sa(int s[], int n, int m)
{
int i, j, p, *x = t1, *y = t2;
for(i = ; i < m; i++)c[i] = ;
for(i = ; i < n; i++)c[x[i] = s[i]]++;
for(i = ; i < m; i++)c[i] += c[i - ];
for(i = n - ; i >= ; i--)sa[--c[x[i]]] = i;
for(j = ; j <= n; j <<= ){
p = ;
for(i = n - j; i < n; i++)y[p++] = i;
for(i = ; i < n; i++)if(sa[i] >= j)y[p++] = sa[i] - j;
for(i = ; i < m; i++)c[i] = ;
for(i = ; i < n; i++)c[x[y[i]]]++;
for(i = ; i < m; i++)c[i] += c[i - ];
for(i = n - ; i >= ; i--)sa[--c[x[y[i]]]] = y[i];
swap(x, y);
p = ;
x[sa[]] = ;
for(i = ; i < n; i++)
x[sa[i]] = y[sa[i - ]] == y[sa[i]] && y[sa[i - ] + j] == y[sa[i] + j] ? p - :p++;
if(p >= n)break;
m = p;
}
} void get_height(int s[], int n)
{
int i, j, k = ;
for(i = ; i <= n; i++)rnk[sa[i]] = i;
for(i = ; i < n; i++){
if(k) k--;
j = sa[rnk[i] - ];
while(s[i + k] == s[j + k])k++;
height[rnk[i]] = k;
}
} int s[maxn];
int main()
{
scanf("%d", &t);
while(t--){
scanf("%s", str);
int n = strlen(str);
for(int i = ; i <= n; i++)s[i] = str[i];
build_sa(s, n + , );
get_height(s, n);
LL ans = n * (n + ) / ;
//cout<<ans<<endl;
for(int i = ; i <= n; i++){
ans -= height[i];
}
printf("%lld\n", ans); }
return ;
}
SPOJ Distinct Substrings【后缀数组】的更多相关文章
- spoj Distinct Substrings 后缀数组
给定一个字符串,求不相同的子串的个数. 假如给字符串“ABA";排列的子串可能: A B A AB BA ABA 共3*(3+1)/2=6种; 后缀数组表示时: A ABA BA 对于A和 ...
- SPOJ - SUBST1 New Distinct Substrings —— 后缀数组 单个字符串的子串个数
题目链接:https://vjudge.net/problem/SPOJ-SUBST1 SUBST1 - New Distinct Substrings #suffix-array-8 Given a ...
- SPOJ - DISUBSTR Distinct Substrings (后缀数组)
Given a string, we need to find the total number of its distinct substrings. Input T- number of test ...
- 【SPOJ – SUBST1】New Distinct Substrings 后缀数组
New Distinct Substrings 题意 给出T个字符串,问每个字符串有多少个不同的子串. 思路 字符串所有子串,可以看做由所有后缀的前缀组成. 按照后缀排序,遍历后缀,每次新增的前缀就是 ...
- SPOJ DISUBSTR Distinct Substrings 后缀数组
题意:统计母串中包含多少不同的子串 然后这是09年论文<后缀数组——处理字符串的有力工具>中有介绍 公式如下: 原理就是加上新的,减去重的,这题是因为打多校才补的,只能说我是个垃圾 #in ...
- SPOJ 694 || 705 Distinct Substrings ( 后缀数组 && 不同子串的个数 )
题意 : 对于给出的串,输出其不同长度的子串的种类数 分析 : 有一个事实就是每一个子串必定是某一个后缀的前缀,换句话说就是每一个后缀的的每一个前缀都代表着一个子串,那么如何在这么多子串or后缀的前缀 ...
- spoj 694. Distinct Substrings 后缀数组求不同子串的个数
题目链接:http://www.spoj.com/problems/DISUBSTR/ 思路: 每个子串一定是某个后缀的前缀,那么原问题等价于求所有后缀之间的不相同的前缀的个数.如果所有的后缀按照su ...
- [spoj694&spoj705]New Distinct Substrings(后缀数组)
题意:求字符串中不同子串的个数. 解题关键:每个子串一定是某个后缀的前缀,那么原问题等价于求所有后缀之间的不相同的前缀的个数. 1.总数减去height数组的和即可. 注意这里height中为什么不需 ...
- SPOJ_705_New Distinct Substrings_后缀数组
SPOJ_705_New Distinct Substrings_后缀数组 题意: 给定一个字符串,求该字符串含有的本质不同的子串数量. 后缀数组的一个小应用. 考虑每个后缀的贡献,如果不要求本质不同 ...
- SPOJ Distinct Substrings(后缀数组求不同子串个数,好题)
DISUBSTR - Distinct Substrings no tags Given a string, we need to find the total number of its dist ...
随机推荐
- 【一步步学OpenGL 21】 -《聚光灯光源》
教程 21 聚光灯光源 原文: http://ogldev.atspace.co.uk/www/tutorial21/tutorial21.html CSDN完整版专栏: http://blog.cs ...
- 8 -- 深入使用Spring -- 4...1 为什么需要AOP
8.4.1 为什么需要AOP AOP专门用于处理系统中分布于各种模块(不同方法)中的交叉关注点的问题,在Java EE应用中,常常通过AOP来处理一些具有横切性质的系统级服务,如事务管理.安全检查.缓 ...
- Go面向对象(三)
go语言中的大多数类型都是值予以,并且都可以包含对应的操作方法,在需要的时候你可以给任意类型增加新方法.二在实现某个接口时,无需从该接口集成,只需要实现该接口要求的所有方法即可.任何类型都可以被any ...
- 个人成长|荣获CNVD年度最有价值漏洞奖
本文共750+字,预计阅读2-3分钟. 前几天,很荣幸受主办方邀请,还拿了CNVD的一个“年度最有价值漏洞奖”,说一说,这几天的故事吧. 11月20号,意外收到一个会议邀请,当时还比较诧异,印象中我在 ...
- C#编写中使用预编译指令代替不停的注释
是不是经常调试某个模块的时候,要打开一堆Console或者Debug.Log,printf 不调试的时候,又关掉.如此繁复的倒腾实在是烦 可以使用预编译指令代替这种做法 #define 自定义字段 . ...
- javaCompileOptions { annotationProcessorOptions { includeCompileClasspath = true } }
一: 在app的build中android { ... defaultConfig { ... //添加如下配置就OK了 javaCompileO ...
- python--列表内建函数的方法
List Method Operation list.append(obj) #向列表中添加一个对象obj list.count(obj) #返回一个对象obj 在列表中出现的次数 ...
- Linux记录用户shell命令
在/etc/profile中添加下面内容: export LC_ALL=C TMOUT=3600 HISTFILESIZE=2000 HISTSIZE=2000 HISTTIMEFORMAT=&quo ...
- IE(兼容问题)错误:缺少标识符 字符串或数字的解决
在IE上遇到一个问题,缺少标识符 字符串或数字的解决. 问题是我的html页面在Firefox.chorme中运行正常,而在IE中老是报“缺少标识符 字符串或数字”的错误,原因: 这就是IE和Fire ...
- 日记整理---->2017-05-17
起始时间是2017-05-17,记录一下spring的学习过程.陌生人可以变成熟人,但熟人一旦变成陌生人,就再也回不去了. 一.测试一下init-method和depend-on huhx.xml文件 ...