spoj694 DISUBSTR - 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.
题目大意:给定一个字符串,求不同的子串数,子串是连续的.
分析:每个子串是对应后缀的前缀,利用后缀数组.
求出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的更多相关文章
- DISUBSTR - Distinct Substrings
DISUBSTR - Distinct Substrings no tags Given a string, we need to find the total number of its dist ...
- SPOJ694 New Distinct Substrings
New Distinct Substrings 题目大意 给定一个字符串,求本质不同的子串个数 题解 SA常见思想:每一个子串都是某个后缀的前缀 考虑每一个后缀的贡献,首先他拥有n - sa[i]个( ...
- SPOJ - DISUBSTR Distinct Substrings (后缀数组)
Given a string, we need to find the total number of its distinct substrings. Input T- number of test ...
- SPOJ DISUBSTR Distinct Substrings 后缀数组
题意:统计母串中包含多少不同的子串 然后这是09年论文<后缀数组——处理字符串的有力工具>中有介绍 公式如下: 原理就是加上新的,减去重的,这题是因为打多校才补的,只能说我是个垃圾 #in ...
- SPOJ 694 DISUBSTR - Distinct Substrings
思路 求本质不同的子串个数,总共重叠的子串个数就是height数组的和 总子串个数-height数组的和即可 代码 #include <cstdio> #include <algor ...
- SP694 DISUBSTR - Distinct Substrings
/* 统计每个节点的max和min, 然后求和即可 min = max[fa] + 1 */ #include<cstdio> #include<algorithm> #inc ...
- 【SPOJ694】Distinct Substrings (SA)
求不相同子串个数 该问题等价于求所有后缀间不相同前缀的个数..也就是对于每个后缀suffix(sa[i]),将贡献出n-sa[i]+1个,但同时,要减去那些重复的,即为height[i],故答案 ...
- SPOJ694 -- DISUBSTR 后缀树组求不相同的子串的个数
DISUBSTR - Distinct Substrings Given a string, we need to find the total number of its distinct su ...
- SPOJ 694&&SPOJ705: Distinct Substrings
DISUBSTR - Distinct Substrings 链接 题意: 询问有多少不同的子串. 思路: 后缀数组或者SAM. 首先求出后缀数组,然后从对于一个后缀,它有n-sa[i]-1个前缀,其 ...
随机推荐
- TW实习日记:第十天
今天任务很简单,就是出品项目的时间轴显示页面和动态路由设置.其实时间轴页面很快就做完了,在做完处理完数据之后,然而有很多细节需要打磨,这就又考验了我面向搜索引擎编程的能力,根据需求百度了很多css的样 ...
- Teaching Machines to Understand Us 让机器理解我们 之一 引言
Teaching Machines to Understand Us By Tom Simonite MIT Technology Review Vol.118 No.5 2015 让机器理解我 ...
- 我想这次我真的理解了 JavaScript 的单线程机制
今天面试的时候被问到一个问题,是关于 JS 异步的.当时我脑海中闪过了一个单线程的概念,但却没有把真正的原理阐述清楚.所以回来特意重新回顾了前面单线程和异步相关的一些知识点. 虽然之前学习的时候也接触 ...
- 使用calendar日历插件实现动态展示会议信息
效果图如下,标红色为有会议安排,并跳转详细会议信息页面. html页面 <%@ page contentType="text/html;charset=UTF-8"%> ...
- [C++基础] 成员变量的初始化顺序
转载链接:https://blog.csdn.net/qq_37059483/article/details/78608375 1.成员变量在使用初始化列表初始化时,只与定义成员变量的顺序有关,与构造 ...
- 你用 Python 做过什么有趣的数据挖掘项目?
有网友在知乎提问:「你用 Python 做过什么有趣的数据挖掘项目?」 我最近刚开始学习 Python, numpy, scipy 等, 想做一些数据方面的项目,但是之前又没有这方面的经验.所以想知道 ...
- HTML页面模板代码
作者声明:本博客中所写的文章,都是博主自学过程的笔记,参考了很多的学习资料,学习资料和笔记会注明出处,所有的内容都以交流学习为主.有不正确的地方,欢迎批评指正 HTML页面模板代码 常用的页面模板 & ...
- Linux系统LVS搭建笔记
因为客户是国有企业,且一次性购买了14台服务器(16核),14台中暂且先用8台,其中LVS使用5台,NFS一台主要为了共享WEB系统(多台电脑的1.5T的硬盘容量浪费了).MySQL两台,Memcac ...
- 使用vue的mixins混入实现对正在编辑的页面离开时提示
mixins.ts import { Vue, Component, Watch } from "vue-property-decorator" Component.registe ...
- 探究Android中通过继承ViewGroup自定义控件的原理
原文地址:http://www.cnblogs.com/kross/p/3378395.html 今天断断续续的折腾了一下午到现在20:38,终于有点明白了.o(╯□╰)o 在Android开发中,我 ...