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. 随笔1-本想吐槽cnblog编辑器,但是今天猛然发现它竟然这么干净简洁

    日常用写作编辑器 多少和我一样有选择综合征的? 不愿意写博客的其中一个非常重要的原因是编辑器不好用! 博客的迁移是相当麻烦的! 所以定下cnblog写东西也是一种勇气!鼓励.... FlashNote ...

  2. (转)ASP.NET Core 性能对比评测(ASP.NET,Python,Java,NodeJS)

    转:https://www.cnblogs.com/savorboard/archive/2016/10/17/dotnet-benchmarks.html 前言 性能是我们日常生活中经常接触到的一个 ...

  3. LibLas学习笔记

    LibLas学习笔记 las  什么是Las格式 LAS文件格式是数据用户之间交换三维点云数据的公共文件格式. 虽然这种格式主要用于交换激光雷达点云数据,但是它支持交换任何三维的x.y.z 数组. 这 ...

  4. 利用Tensorflow进行自然语言处理(NLP)系列之一Word2Vec

    同步笔者CSDN博客(https://blog.csdn.net/qq_37608890/article/details/81513882). 一.概述 本文将要讨论NLP的一个重要话题:Word2V ...

  5. 第八次ScrumMeeting博客

    第八次ScrumMeeting博客 本次会议于11月2日(四)22时整在3公寓725房间召开,持续20分钟. 与会人员:刘畅.辛德泰.窦鑫泽.张安澜.赵奕.方科栋. 1. 每个人的工作(有Issue的 ...

  6. scrum立会报告+燃尽图(第三周第五次)

    此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2286 项目地址:https://coding.net/u/wuyy694 ...

  7. request.quest/query_string/params/body等方法介绍

    假设url:http://192.168.1.111:8080/api/cluster/group?wzd=111&abc=cc 方法类型:POST,body是{"name" ...

  8. 【技术向】rainmeter的设计与发现

    我们在大学期间所学的那点代码知识还远远不够,于是我就自己寻找到了一款简单易懂的软件,来丰富我的代码知识. 这款软件叫rainmeter,中文叫做雨滴,是一款可以修改桌面的软件.它可以将桌面上更改出硬盘 ...

  9. mui.ajax与服务器(SpringMVC)传输json数据

    跨域问题 PC端为了安全,所以禁止跨域.而我使用mui做移动web时,难免会使用pc浏览器进行调试.mui.ajax是允许跨域的.为了可以调试成功,需要对浏览器进行设置及.以360急速浏览器为例,设置 ...

  10. NULL指针引起的一个linux内核漏洞

    NULL指针一般都是应用于有效性检测的,其实这里面有一个约定俗成的规则,就是说无效指针并不一定是 NULL,只是为了简单起见,规则约定只要指针无效了就将之设置为NULL,结果就是NULL这个指针被用来 ...