Distinct Substrings SPOJ - DISUBSTR 后缀数组
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.
那么这个问题就转化成了所有后缀中不相同的前缀一共有多少个
但是有重复的,重复个数就是height[i]
所有不重复前缀是n-sa[i]+1-height[i]
这样的话就会导致最后的答案少计算
这个新长度的字符串求解
1 #include <cstdio>
2 #include <cstring>
3 #include <algorithm>
4 #define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
5 #define G(x) ((x) < tb ? (x) * 3 + 1 : ((x) - tb) * 3 + 2)
6 using namespace std;
7 const int N = 1005;
8 int c[N],sa[N*3];
9 int ranks[N*3], height[N*3],s[N];
10 char str[N];
11 bool pan(int *x,int i,int j,int k,int n)
12 {
13 int ti=i+k<n?x[i+k]:-1;
14 int tj=j+k<n?x[j+k]:-1;
15 return x[i]==x[j]&&ti==tj;
16 }
17 void build_SA(int n,int r)
18 {
19 int *x=ranks,*y=height;
20 for(int i=0; i<r; i++)c[i]=0;
21 for(int i=0; i<n; i++)c[s[i]]++;
22 for(int i=1; i<r; i++)c[i]+=c[i-1];
23 for(int i=n-1; i>=0; i--)sa[--c[s[i]]]=i;
24 r=1;
25 x[sa[0]]=0;
26 for(int i=1; i<n; i++)
27 x[sa[i]]=s[sa[i]]==s[sa[i-1]]?r-1:r++;
28 for(int k=1; r<n; k<<=1)
29 {
30 int yn=0;
31 for(int i=n-k; i<n; i++)y[yn++]=i;
32 for(int i=0; i<n; i++)
33 if(sa[i]>=k)y[yn++]=sa[i]-k;
34 for(int i=0; i<r; i++)c[i]=0;
35 for(int i=0; i<n; i++)++c[x[y[i]]];
36 for(int i=1; i<r; i++)c[i]+=c[i-1];
37 for(int i=n-1; i>=0; i--)sa[--c[x[y[i]]]]=y[i];
38 swap(x,y);
39 r=1;
40 x[sa[0]]=0;
41 for(int i=1; i<n; i++)
42 x[sa[i]]=pan(y,sa[i],sa[i-1],k,n)?r-1:r++;
43 }
44 for(int i=0; i<n; i++)ranks[i]=x[i];
45 }
46 void get_height(int n)
47 {
48 int i,j,k=0;
49 for(i=1; i<=n; i++)ranks[sa[i]]=i;
50 for(i=0; i<n; i++)
51 {
52 if(k)k--;
53 else k=0;
54 j=sa[ranks[i]-1];
55 while(s[i+k]==s[j+k])k++;
56 height[ranks[i]]=k;
57 }
58 }
59 int main() {
60 int t;
61 scanf("%d", &t);
62 while (t--) {
63 scanf("%s", str);
64 int len = strlen(str);
65 for (int i = 0; i < len; i++)
66 s[i] = (int)str[i];
67 s[len] = 0;
68 build_SA(len+1,200);
69 get_height(len);
70 int res = 0;
71 for (int i = 1; i <= len; i++)
72 //printf("%d ",height[i]),
73 res += ((len-1) - sa[i]+1 - height[i]);
74 printf("%d\n", res);
75 }
76 return 0;
77 }
形成的height就是结果
1 #include <cstdio>
2 #include <cstring>
3 #include <algorithm>
4 #define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
5 #define G(x) ((x) < tb ? (x) * 3 + 1 : ((x) - tb) * 3 + 2)
6 using namespace std;
7 const int N = 1005;
8 int c[N],sa[N*3];
9 int ranks[N*3], height[N*3],s[N];
10 char str[N];
11 bool pan(int *x,int i,int j,int k,int n)
12 {
13 int ti=i+k<n?x[i+k]:-1;
14 int tj=j+k<n?x[j+k]:-1;
15 return x[i]==x[j]&&ti==tj;
16 }
17 void build_SA(int n,int r)
18 {
19 int *x=ranks,*y=height;
20 for(int i=0; i<r; i++)c[i]=0;
21 for(int i=0; i<n; i++)c[s[i]]++;
22 for(int i=1; i<r; i++)c[i]+=c[i-1];
23 for(int i=n-1; i>=0; i--)sa[--c[s[i]]]=i;
24 r=1;
25 x[sa[0]]=0;
26 for(int i=1; i<n; i++)
27 x[sa[i]]=s[sa[i]]==s[sa[i-1]]?r-1:r++;
28 for(int k=1; r<n; k<<=1)
29 {
30 int yn=0;
31 for(int i=n-k; i<n; i++)y[yn++]=i;
32 for(int i=0; i<n; i++)
33 if(sa[i]>=k)y[yn++]=sa[i]-k;
34 for(int i=0; i<r; i++)c[i]=0;
35 for(int i=0; i<n; i++)++c[x[y[i]]];
36 for(int i=1; i<r; i++)c[i]+=c[i-1];
37 for(int i=n-1; i>=0; i--)sa[--c[x[y[i]]]]=y[i];
38 swap(x,y);
39 r=1;
40 x[sa[0]]=0;
41 for(int i=1; i<n; i++)
42 x[sa[i]]=pan(y,sa[i],sa[i-1],k,n)?r-1:r++;
43 }
44 for(int i=0; i<n; i++)ranks[i]=x[i];
45 }
46 void get_height(int n)
47 {
48 int i,j,k=0;
49 for(i=1; i<=n; i++)ranks[sa[i]]=i;
50 for(i=0; i<n; i++)
51 {
52 if(k)k--;
53 else k=0;
54 j=sa[ranks[i]-1];
55 while(s[i+k]==s[j+k])k++;
56 height[ranks[i]]=k;
57 }
58 }
59 int main()
60 {
61 int t;
62 scanf("%d", &t);
63 while (t--)
64 {
65 scanf("%s", str);
66 int len = strlen(str);
67 for (int i = 0; i < len; i++)
68 s[i] = (int)str[i];
69 s[len] = 0;
70 build_SA(len+1,200);
71 get_height(len);
72 int res = ((len+1)*len)/2;
73 for (int i = 2; i <= len; i++)
74 //printf("%d ",height[i]),
75 res -= height[i];
76 printf("%d\n", res);
77 }
78 return 0;
79 }
Distinct Substrings SPOJ - DISUBSTR 后缀数组的更多相关文章
- Distinct Substrings SPOJ - DISUBSTR(后缀数组水题)
求不重复的子串个数 用所有的减去height就好了 推出来的... #include <iostream> #include <cstdio> #include <sst ...
- Spoj-DISUBSTR - Distinct Substrings~New Distinct Substrings SPOJ - SUBST1~(后缀数组求解子串个数)
Spoj-DISUBSTR - Distinct Substrings New Distinct Substrings SPOJ - SUBST1 我是根据kuangbin的后缀数组专题来的 这两题题 ...
- 705. New Distinct Substrings spoj(后缀数组求所有不同子串)
705. New Distinct Substrings Problem code: SUBST1 Given a string, we need to find the total number o ...
- SPOJ DISUBSTR 后缀数组
题目链接:http://www.spoj.com/problems/DISUBSTR/en/ 题意:给定一个字符串,求不相同的子串个数. 思路:直接根据09年oi论文<<后缀数组——出来字 ...
- SPOJ DISUBSTR ——后缀数组
[题目分析] 后缀数组模板题. 由于height数组存在RMQ的性质. 那么对于一个后缀,与前面相同的串总共有h[i]+sa[i]个.然后求和即可. [代码](模板来自Claris,这个板子太漂亮了) ...
- [spoj DISUBSTR]后缀数组统计不同子串个数
题目链接:https://vjudge.net/contest/70655#problem/C 后缀数组的又一神奇应用.不同子串的个数,实际上就是所有后缀的不同前缀的个数. 考虑所有的后缀按照rank ...
- SPOJ 694 Distinct Substrings/SPOJ 705 New Distinct Substrings(后缀数组)
Given a string, we need to find the total number of its distinct substrings. Input T- number of test ...
- Distinct Substrings(spoj694)(sam(后缀自动机)||sa(后缀数组))
Given a string, we need to find the total number of its distinct substrings. Input \(T-\) number of ...
- SPOJ694 DISUBSTR --- 后缀数组 / 后缀自动机
SPOJ694 DISUBSTR 题目描述: Given a string, we need to find the total number of its distinct substrings. ...
随机推荐
- Centos 7 杂章
CentOS-7-x86_64-DVD-2003.iso 下载地址: http://mirrors.aliyun.com/centos/7/isos/x86_64/CentOS-7-x86_64-DV ...
- 十八:SQL注入之堆叠及绕WAF
堆叠查询注入 (双查询注入) stacked injections(堆叠注入)从名词的含义就可以看到是一堆的SQL语句一起执行,而在真实的运用中也是这样的,我们知道在mysql中,主要是命令行中,每一 ...
- CPNDet:粗暴地给CenterNet加入two-stage精调,更快更强 | ECCV 2020
本文为CenterNet作者发表的,论文提出anchor-free/two-stage目标检测算法CPN,使用关键点提取候选框再使用两阶段分类器进行预测.论文整体思路很简单,但CPN的准确率和推理速度 ...
- 【Linux】如何查找命令及历史记录history
如何查找命令及历史记录 文章目录 如何查找命令及历史记录 1.如何找到一个命令 2.命令的历史记录 3.一些实用的快捷键 4.小结 5.参考资料 如何找到一个命令.命令的历史记录.一些实用的快捷键.总 ...
- ctfhub技能树—web前置技能—http协议—Cookie
打开靶机环境 查看显示内容 根据提示,需要admin登录才能得到flag 题目介绍为Cookie欺骗.认证.伪造 介绍一下cookie和session 一.cookie: 在网站中,http请求是无状 ...
- Java高并发与多线程(四)-----锁
今天,我们开始Java高并发与多线程的第四篇,锁. 之前的三篇,基本上都是在讲一些概念性和基础性的东西,东西有点零碎,但是像文科科目一样,记住就好了. 但是本篇是高并发里面真正的基石,需要大量的理解和 ...
- mysql半同步复制跟无损半同步区别
mysql半同步复制跟无损半同步复制的区别: 无损复制其实就是对semi sync增加了rpl_semi_sync_master_wait_point参数,来控制半同步模式下主库在返回给会话事务成功之 ...
- Cisco IOS
IOS Internetwork Operating System 互联网操作系统(基于UNIX系统) Cisco IOS 软件提供多种网络服务进而支持各种网络应用. Cisco IOS用户界面的基本 ...
- Java面向对象(三)—— 继承
标签: java 继承 抽象类 this super abstract 概述 多个类中存在相同的属性和行为的时候,将这些内容抽取到单独一个类中,那么多个类无需在定义这些属性和行为,只要继承那个类即可. ...
- nginx proxy pass redirects ignore port
nginx proxy pass redirects ignore port $host in this order of precedence: host name from the request ...