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. [leetcode]三数之和

    三数之和 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组. 注意:答案中不可以包含重复 ...

  2. phpcms v9如何给父级单页栏目添加内容

    对于phpcms单页的调用相信大家都应该没问题,那么如果我们在后台添加的单页有二层甚至更多的时候,这样在管理内容上是没有给父级栏目添加内容这一功能的!那么我们该怎么实现这个功能并调用呢? 首先我们要修 ...

  3. day04 list tuple (补)

    今日内容: 1. 列表 2. 列表的增删改查 3. 列表的嵌套 4. 元组和元组嵌套 5. range 列表 列表: 能装对象的对象. 有顺序的(按照我们添加的顺序保存) 在代码中使用[]表示列表. ...

  4. DOM---文档对象模型(Document Object Model)的基本使用

    一.DOM简介 文档对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展置标语言的标准编程接口.它是一种与平台和语言无关的应用程序接口(API),它可以动态 ...

  5. Paper Reading - Deep Visual-Semantic Alignments for Generating Image Descriptions ( CVPR 2015 )

    Link of the Paper: https://arxiv.org/abs/1412.2306 Main Points: An Alignment Model: Convolutional Ne ...

  6. java面向对象的有序数组和无序数组的比较

    package aa; class Array{ //定义一个有序数组 private long[] a; //定义数组长度 private int nElems; //构造函数初始化 public ...

  7. 软件工程 - 第二十次作业 Alpha 事后诸葛亮(团队)

    Alpha 事后诸葛亮(团队) 组长本次作业链接:https://www.cnblogs.com/dawnduck/p/10056026.html 现代软件工程 项目Postmortem 设想和目标 ...

  8. Web站点性能-微观手段

    文章:网站性能优化 百度百科:高性能Web站点 文章:构建高性能WEB站点之 吞吐率.吞吐量.TPS.性能测试

  9. 03_Java基础语法_第3天(Scanner、Random、流程控制语句)_讲义

    今日内容介绍 1.引用类型变量的创建及使用 2.流程控制语句之选择语句 3.流程控制语句之循环语句 4.循环高级 01创建引用类型变量公式 * A: 创建引用类型变量公式 * a: 我们要学的Scan ...

  10. Java & hashCode作用

    首先,想要明白hashCode的作用,你必须要先知道Java中的集合. 总的来说,Java中的集合(Collection)有两类,一类是List,再有一类是Set.你知道它们的区别吗?前者集合内的元素 ...