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.

题意:

为字符串的子串个数

思路:

使用后缀数组解决。

按sa遍历后缀数组,每一个后缀的贡献即为n-sa[i]-lcp[i];

这里的lcp就是你们所说的height

#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime> #define fuck(x) cout<<#x<<" = "<<x<<endl;
#define debug(a, x) cout<<#a<<"["<<x<<"] = "<<a[x]<<endl;
#define ls (t<<1)
#define rs ((t<<1)|1)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = ;
const int maxm = ;
const int inf = 0x3f3f3f3f;
const ll Inf = ;
const int mod = ;
const double eps = 1e-;
const double pi = acos(-); char s[maxn];
int len,Rank[maxn],sa[maxn],k,tmp[maxn];
bool compare_sa(int i, int j) {
if (Rank[i] != Rank[j]) { return Rank[i] < Rank[j]; }
//如果以i开始,长度为k的字符串的长度,已经超出了字符串尾,那么就赋值为-1
//这是因为,在前面所有数据相同的情况下,字符串短的字典序小.
int ri = i + k <= len ? Rank[i + k] : -inf;
int rj = j + k <= len ? Rank[j + k] : -inf;
return ri < rj;
} void construct_sa() {
//初始的RANK为字符的ASCII码
for (int i = ; i <= len; i++) {
sa[i] = i;
Rank[i] = i < len ? s[i] : -inf;
}
for (k = ; k <= len; k *= ) {
sort(sa, sa + len + , compare_sa);
tmp[sa[]] = ;
//全新版本的RANK,tmp用来计算新的rank
//将字典序最小的后缀rank计为0
//sa之中表示的后缀都是有序的,所以将下一个后缀与前一个后缀比较,如果大于前一个后缀,rank就比前一个加一.
//否则就和前一个相等.
for (int i = ; i <= len; i++) {
tmp[sa[i]] = tmp[sa[i - ]] + (compare_sa(sa[i - ], sa[i]) ? : );
}
for (int i = ; i <= len; i++) {
Rank[i] = tmp[i]; }
}
}
int lcp[maxn]; void construct_lcp(){
// for(int i=0;i<=n;i++){Rank[sa[i]]=i;} int h=;
lcp[]=;
for(int i=;i<len;i++){//i为后缀数组起始位置
int j = sa[Rank[i]-];//获取当前后缀的前一个后缀(排序后)
if(h>)h--;
for(;j+h<len&&i+h<len;h++){
if(s[j+h]!=s[i+h])break;
}
lcp[Rank[i]]=h;
}
} int main() {
int T;
scanf("%d",&T);
while (T--){
scanf("%s",s);
len = strlen(s);
construct_sa();
construct_lcp(); int ans=;
for(int i=;i<=len;i++){
ans+=(len-sa[i]-lcp[i]);
}
printf("%d\n",ans);
} return ;
}

SPOJ - DISUBSTR Distinct Substrings (后缀数组)的更多相关文章

  1. SPOJ DISUBSTR Distinct Substrings 后缀数组

    题意:统计母串中包含多少不同的子串 然后这是09年论文<后缀数组——处理字符串的有力工具>中有介绍 公式如下: 原理就是加上新的,减去重的,这题是因为打多校才补的,只能说我是个垃圾 #in ...

  2. spoj 694. Distinct Substrings 后缀数组求不同子串的个数

    题目链接:http://www.spoj.com/problems/DISUBSTR/ 思路: 每个子串一定是某个后缀的前缀,那么原问题等价于求所有后缀之间的不相同的前缀的个数.如果所有的后缀按照su ...

  3. SPOJ - SUBST1 New Distinct Substrings —— 后缀数组 单个字符串的子串个数

    题目链接:https://vjudge.net/problem/SPOJ-SUBST1 SUBST1 - New Distinct Substrings #suffix-array-8 Given a ...

  4. 【SPOJ – SUBST1】New Distinct Substrings 后缀数组

    New Distinct Substrings 题意 给出T个字符串,问每个字符串有多少个不同的子串. 思路 字符串所有子串,可以看做由所有后缀的前缀组成. 按照后缀排序,遍历后缀,每次新增的前缀就是 ...

  5. SPOJ 694 || 705 Distinct Substrings ( 后缀数组 && 不同子串的个数 )

    题意 : 对于给出的串,输出其不同长度的子串的种类数 分析 : 有一个事实就是每一个子串必定是某一个后缀的前缀,换句话说就是每一个后缀的的每一个前缀都代表着一个子串,那么如何在这么多子串or后缀的前缀 ...

  6. spoj Distinct Substrings 后缀数组

    给定一个字符串,求不相同的子串的个数. 假如给字符串“ABA";排列的子串可能: A B A AB  BA ABA 共3*(3+1)/2=6种; 后缀数组表示时: A ABA BA 对于A和 ...

  7. ●SPOJ 8222 NSUBSTR - Substrings(后缀数组)

    题链: http://www.spoj.com/problems/NSUBSTR/ 题解: 同届红太阳 --WSY给出的后缀数组解法!!! 首先用倍增算法求出 sa[i],rak[i],hei[i]然 ...

  8. [spoj694&spoj705]New Distinct Substrings(后缀数组)

    题意:求字符串中不同子串的个数. 解题关键:每个子串一定是某个后缀的前缀,那么原问题等价于求所有后缀之间的不相同的前缀的个数. 1.总数减去height数组的和即可. 注意这里height中为什么不需 ...

  9. 【SPOJ】Distinct Substrings/New Distinct Substrings(后缀数组)

    [SPOJ]Distinct Substrings/New Distinct Substrings(后缀数组) 题面 Vjudge1 Vjudge2 题解 要求的是串的不同的子串个数 两道一模一样的题 ...

随机推荐

  1. Ubuntu里node命令出错,找不到

    ubuntu里用sudo apt-get install nodejs安装Node.js后, 发现terminals里运行node命令(比如node –-version)时候会有No such fil ...

  2. 基于GD库的php验证码类(支持中英文字体、背景、干扰点线、扭曲…….)

    转自:http://www.blhere.com/1168.html 12345678910111213141516171819202122232425262728293031323334353637 ...

  3. NPOI操作、导出Excel

    //使用NPOI操作Excel private void ExcelNPOI(System.Data.DataTable dt, HttpContext context) { IWorkbook wo ...

  4. jQuery $.isNumeric vs. $.isNaN vs. isNaN

    在jQuery中,有几种方式可以判断一个对象是否是数字,或者可否转换为数字. 首先,jQuery.isNaN()在最新版本中已经被移除了(1.7之后),取而代之的是  jQuery.isNumeric ...

  5. BZOJ1878 洛谷1972 HH的项链题解

    洛谷链接 BZOJ链接 看到这样不用修改的题目,应该佷容易就联想到了离线来处理. 我们发现若将询问按照r来排序,排完后每次对答案有贡献的仅是每个颜色最后出现的位置 我们用next[i]表示i处颜色之前 ...

  6. poj 2342 hdu 1520【树形dp】

    poj 2342 给出每个顶点的happy值,还有若干组两个顶点L,K关系,表示K是L的上司.求当K.L不同时出现时获得的happy值的最大和. 设dp[u][0]表示不选u结点时获得的最大值,dp[ ...

  7. qt 中lineEdit->setText()输出double

    在qt中需要将获取到的double 值在ui界面上显示出来,便于观察.但是lineEdit控件的setText()要求的参数是string. 所以我们先要进行转化,将double 转化为string. ...

  8. 05Dockerfile简介

    Dockerfile是一个用于构建Docker镜像的文本文件,其中包含了创建Docker镜像的全部指令.基于这些指令,可以使用"docker  build"命令来创建镜像. 一:用 ...

  9. HZOJ 匹配

    Hash/KMP裸题,并不想写什么,只是复习一下KMP吧. void get_n() { next[]=; ; ;i<=lt;i++) { && t[i]!=t[j+])j=ne ...

  10. 一些关于中国剩余定理的数论题(POJ 2891/HDU 3579/HDU 1573/HDU 1930)

    2891 -- Strange Way to Express Integers import java.math.BigInteger; import java.util.Scanner; publi ...