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和ht数组. 对于每个sa[i],它能和它本身以及后面的字符形成子串,如果固定sa[i]为子串的左端点,那么它能形成n-sa[i]个子串. 所有的子串加起来等于Σn - sa[i] = n*(n + 1) / 2.

   这样统计会将某些子串重复统计. 因为ht数组计算的是排好序的两个相邻后缀的LCP,如果有重叠部分,那么一定是最大的.对于每一个sa[i],他会重复计算ht[i]个子串(固定了左端点嘛,这一段的右端点也是一样的,那么就会重复计算了).减掉就好了.

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; const int maxn = ;
int n,ans,fir[maxn],sec[maxn],pos[maxn],sa[maxn],rk[maxn],tong[maxn],ht[maxn];
int sett[maxn],a[maxn],cnt,K,T;
char s[maxn]; void solve()
{
int len = n;
memset(rk,,sizeof(rk));
memset(sa,,sizeof(sa));
memset(ht,,sizeof(ht));
memset(fir,,sizeof(fir));
memset(sec,,sizeof(sec));
memset(pos,,sizeof(pos));
memset(tong,,sizeof(tong));
copy(s + ,s + len + ,sett + );
sort(sett + ,sett + + len);
cnt = unique(sett + ,sett + + len) - sett - ;
for (int i = ; i <= len; i++)
a[i] = lower_bound(sett + ,sett + + cnt,s[i]) - sett;
for (int i = ; i <= len; i++)
tong[a[i]]++;
for (int i = ; i <= len; i++)
tong[i] += tong[i - ];
for (int i = ; i <= len; i++)
rk[i] = tong[a[i] - ] + ;
for (int t = ; t <= len; t *= )
{
for (int i = ; i <= len; i++)
fir[i] = rk[i];
for (int i = ; i <= len; i++)
{
if (i + t > len)
sec[i] = ;
else
sec[i] = rk[i + t];
}
fill(tong,tong + + len,);
for (int i = ; i <= len; i++)
tong[sec[i]]++;
for (int i = ; i <= len; i++)
tong[i] += tong[i - ];
for (int i = ; i <= len; i++)
pos[len - --tong[sec[i]]] = i;
fill(tong,tong + + len,);
for (int i = ; i <= len; i++)
tong[fir[i]]++;
for (int i = ; i <= len; i++)
tong[i] += tong[i - ];
for (int i = ; i <= len; i++)
{
int temp = pos[i];
sa[tong[fir[temp]]--] = temp;
}
bool flag = true;
int last = ;
for (int i = ; i <= len; i++)
{
int temp = sa[i];
if (!last)
rk[temp] = ;
else if (fir[temp] == fir[last] && sec[temp] == sec[last])
{
rk[temp] = rk[last];
flag = false;
}
else
rk[temp] = rk[last] + ;
last = temp;
}
if (flag)
break;
}
int k = ;
for (int i = ; i <= len; i++)
{
if (rk[i] == )
k = ;
else
{
if (k)
k--;
int j = sa[rk[i] - ];
while (i + k <= len && j + k <= len && a[i + k] == a[j + k])
k++;
}
ht[rk[i]] = k;
}
} int main()
{
scanf("%d",&T);
while (T--)
{
scanf("%s",s + );
n = strlen(s + );
solve();
ans = n * (n + ) / ;
for (int i = ; i <= n; i++)
ans -= ht[i];
printf("%d\n",ans);
} return ;
}

spoj694 DISUBSTR - Distinct Substrings的更多相关文章

  1. DISUBSTR - Distinct Substrings

    DISUBSTR - Distinct Substrings no tags  Given a string, we need to find the total number of its dist ...

  2. SPOJ694 New Distinct Substrings

    New Distinct Substrings 题目大意 给定一个字符串,求本质不同的子串个数 题解 SA常见思想:每一个子串都是某个后缀的前缀 考虑每一个后缀的贡献,首先他拥有n - sa[i]个( ...

  3. SPOJ - DISUBSTR Distinct Substrings (后缀数组)

    Given a string, we need to find the total number of its distinct substrings. Input T- number of test ...

  4. SPOJ DISUBSTR Distinct Substrings 后缀数组

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

  5. SPOJ 694 DISUBSTR - Distinct Substrings

    思路 求本质不同的子串个数,总共重叠的子串个数就是height数组的和 总子串个数-height数组的和即可 代码 #include <cstdio> #include <algor ...

  6. SP694 DISUBSTR - Distinct Substrings

    /* 统计每个节点的max和min, 然后求和即可 min = max[fa] + 1 */ #include<cstdio> #include<algorithm> #inc ...

  7. 【SPOJ694】Distinct Substrings (SA)

    求不相同子串个数    该问题等价于求所有后缀间不相同前缀的个数..也就是对于每个后缀suffix(sa[i]),将贡献出n-sa[i]+1个,但同时,要减去那些重复的,即为height[i],故答案 ...

  8. SPOJ694 -- DISUBSTR 后缀树组求不相同的子串的个数

    DISUBSTR - Distinct Substrings   Given a string, we need to find the total number of its distinct su ...

  9. SPOJ 694&&SPOJ705: Distinct Substrings

    DISUBSTR - Distinct Substrings 链接 题意: 询问有多少不同的子串. 思路: 后缀数组或者SAM. 首先求出后缀数组,然后从对于一个后缀,它有n-sa[i]-1个前缀,其 ...

随机推荐

  1. 接口测试工具Postman接口测试图文教程

    Postman接口测试工具使用 一.前言     在前后端分离开发时,后端工作人员完成系统接口开发后,需要与前端人员对接,测试调试接口,验证接口的正确性可用性.而这要求前端开发进度和后端进度保持基本一 ...

  2. Python科学计算库灬numpy

    Numpy NumPy是一个功能强大的Python库,主要用于对多维数组执行计算.Numpy许多底层函数实际上是用C编写的,因此它的矩阵向量计算速度是原生Python中无法比拟的. numpy属性 维 ...

  3. Java:有关try、catch和finally的学习(供自己参考)

    Java:有关try.catch和finally的学习 在看到书本的时候对finally的介绍是:不论是否在try块中产生异常,都会执行finally.当时对这句话的理解不够深,误以为在try...c ...

  4. 《C》数据类型

  5. 安装cocoa pods

    1.移除现有Ruby默认源 $gem sources --remove https://rubygems.org/ 2.使用新的源 $gem sources -a https://ruby.taoba ...

  6. 读我是一只IT小小鸟有感

    进入大学半年了,每个人都说软件工程是一个非常有前途的高薪职业,但我这半年来都很迷茫,看不清自己的未来,不知道如何度过接下来的三年半时光,虽然我也认为软件工程是有前途的专业,但是经过一学期的学习,发现不 ...

  7. 【week12】psp

    psp 项目 内容 开始时间 结束时间 被打断 净时间 12月2日 写博客 对各小组评价 11:20 12:05 0 45 写博客 final评价1 23:40 23:57 0 17 12月5日 看论 ...

  8. 关于解决java读取excel文件遇空行抛空指针的问题 !

    关于解决java读取excel文件遇空行抛空指针的问题 ! package exceRead; import java.io.File; import java.io.FileInputStream; ...

  9. PHP之array_flip()方法

    array_flip — 交换数组中的键和值 array array_flip ( array $trans ) array_flip() 返回一个反转后的 array,例如 trans 中的键名变成 ...

  10. [BinaryTree] 二叉树常考知识点

    1.二叉树第i层至多有2^(i-1)个结点(i>=1). 2.深度为k的二叉树上,至多含2^k-1个结点(k>=1) 3.n0 = n2 + 1(度) 4.满二叉树:深度为k且含有2^k- ...