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个前缀,其 ...
随机推荐
- HDU-2844:Coins(多重背包+二进制优化)
链接:HDU-2844:Coins 题意:给你n个种类的钱和对应的数量,同统计一下从1到m能够凑成的钱有多少个. 题解:C[i] = 1 + 2 + 4 + ··· + 2^k + a (0 < ...
- 【MySQL解惑笔记】Mysql5.7.x无法开启二进制日志
一.开启二进制日志 1)未开启二进制日志之前: mysql> show variables like 'log_bin'; +---------------+-------+ | Variabl ...
- oozie的shell-action中加入hive脚本命令启动执行shell同时操作hive,抛异常Container killed on request. Exit code is 143 Container exited with a non-zero exit code 143
使用oozie来调度操作,用shell的action执行命令,其中shell里包含着hive -e 操作执行时,oozie窗口报 WARN ShellActionExecutor: - SERVER[ ...
- 带你玩转JavaScript中的隐式强制类型转换
正题开始前我想先抛出一个问题,==和===有什么区别?可能一般人会想,不就是后者除了比较值相等之外还会比较类型是否相等嘛,有什么好问的,谁不知道?!但是这样说还不够准确,两者的真正区别其实是==在比较 ...
- Live Archive 训练题
7091 Height Ordering Mrs. Chambers always has her class line up in height order (shortest at the fro ...
- Scrum立会报告+燃尽图(Beta阶段第二周第四次)
此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2412 项目地址:https://coding.net/u/wuyy694 ...
- Beta冲刺第二周王者荣耀交流协会第三次会议
1.例会照片: 成员王超,高远博,冉华,王磊,王玉玲,任思佳,袁玥全部到齐 master:袁玥 2.时间跨度: 2017年11月19日 17:00 — 17:11,总计11分钟. 3.地 点: 一食堂 ...
- 总结在Visual Studio Code运行node.js项目遇到的问题
一.cannot find module “lodash” 项目运行时出现以下错误: Error: Cannot find module 'lodash' at Function.Module._re ...
- P4语法(5) Package
Package 对于package这个概念,类似于将一个框架中各组成部件以一个规律进行打包,以正常运转. 基于一个架构去编写一个新的pipeline的时候,需要先了解初始化的时候需要提供那些东西,pa ...
- 周总结<5>
周次 学习时间 新编写代码行数 博客量(篇) 学到知识点 12 10 100 1 路由器的设置(ospf协议):网页设计:哈夫曼树(C语言数构) Html案例: <!DOCTYPE html P ...