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.

解法一、
所有的子串都可以通过某个后缀的前缀得到
那么这个问题就转化成了所有后缀中不相同的前缀一共有多少个
先说一个后缀suffix(sa[i])可以产生n-sa[i]+1个前缀
但是有重复的,重复个数就是height[i]
所有不重复前缀是n-sa[i]+1-height[i]
注意第0号后缀是没法和第-1号后缀比较(因为第-1号后缀就不存在)
这样的话就会导致最后的答案少计算
这里采用的方法就是给这个字符串后面加一个未出现过的字符
这个新长度的字符串求解
 
 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 }
 
解法二、
先请出来一共有多少子串,即(n+1)*n/2个,然后height数组的值就是相同前缀的数量,所以用总个数减去这个字符串的所有后缀
形成的height就是结果
因为我的代码在原字符串基础上添加了一个字符,所以第0号后缀不是原字符串的,所以for循环从2到n
 
 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 后缀数组的更多相关文章

  1. Distinct Substrings SPOJ - DISUBSTR(后缀数组水题)

    求不重复的子串个数 用所有的减去height就好了 推出来的... #include <iostream> #include <cstdio> #include <sst ...

  2. Spoj-DISUBSTR - Distinct Substrings~New Distinct Substrings SPOJ - SUBST1~(后缀数组求解子串个数)

    Spoj-DISUBSTR - Distinct Substrings New Distinct Substrings SPOJ - SUBST1 我是根据kuangbin的后缀数组专题来的 这两题题 ...

  3. 705. New Distinct Substrings spoj(后缀数组求所有不同子串)

    705. New Distinct Substrings Problem code: SUBST1 Given a string, we need to find the total number o ...

  4. SPOJ DISUBSTR 后缀数组

    题目链接:http://www.spoj.com/problems/DISUBSTR/en/ 题意:给定一个字符串,求不相同的子串个数. 思路:直接根据09年oi论文<<后缀数组——出来字 ...

  5. SPOJ DISUBSTR ——后缀数组

    [题目分析] 后缀数组模板题. 由于height数组存在RMQ的性质. 那么对于一个后缀,与前面相同的串总共有h[i]+sa[i]个.然后求和即可. [代码](模板来自Claris,这个板子太漂亮了) ...

  6. [spoj DISUBSTR]后缀数组统计不同子串个数

    题目链接:https://vjudge.net/contest/70655#problem/C 后缀数组的又一神奇应用.不同子串的个数,实际上就是所有后缀的不同前缀的个数. 考虑所有的后缀按照rank ...

  7. 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 ...

  8. Distinct Substrings(spoj694)(sam(后缀自动机)||sa(后缀数组))

    Given a string, we need to find the total number of its distinct substrings. Input \(T-\) number of ...

  9. SPOJ694 DISUBSTR --- 后缀数组 / 后缀自动机

    SPOJ694 DISUBSTR 题目描述: Given a string, we need to find the total number of its distinct substrings. ...

随机推荐

  1. scaffoldingTools

    脚手架工具 脚手架工具概要(前端工程化的发起者) 脚手架的本质作用:创建项目基础架构.提供项目规范和约定 相同的组织结构 相同的开发规范 相同的模块依赖 相同的工具配置 相同的基础代码 举例:IDE创 ...

  2. maven打包项目

    使用maven可以对项目进行很方便的管理,方便体现之一便是项目的打包发布变得方便,本文主要是讲一下maven打包时的一些命令和注意事项(皆是自己从应用中总结的理解,或有不对之处). maven项目打包 ...

  3. 网件wndr4300 ttl连接

    路由成砖而还能进入cfe或uboot等情况下,可以通过ttl快速救砖. r4300主板有TTL的接线脚,脚的顺序可以找在OpenWrt的wiki上找到. 如下图4个TTL针在左下角,从下往上分别是GN ...

  4. centos7 开放指定端口

    centos7 开放指定端口 #开放8080端口 firewall-cmd --zone=public --add-port=8080/tcp --permanent #重载防火墙 firewall- ...

  5. Docker 如何动态给SpringBoot项目传参

    关于SpringBoot配置数据源 在项目开发中,我们往往需要配置多套不同的配置环境例如:本地开发.测试环境.部署环境.每一个环境的数据源配置可能都不同,因此需要写不同的数据源配置.如果用Docker ...

  6. Django的数据库读写分离

    Django的数据库读写分离 1.首先是配置数据库 在settings.py文件中增加多个数据库的配置: DATABASES = { 'default': { 'ENGINE': 'django.db ...

  7. JavaScript中的深拷贝和浅拷贝!【有错误】还未修改!请逛其他园子!

    JavaScript中的深拷贝和浅拷贝! 浅拷贝 1.浅拷贝只是拷贝一层,更深层次对象级别的只拷贝引用.{也就是拷贝的是地址!简而言之就是在新的对象中修改深层次的值也会影响原来的对象!} // 2.深 ...

  8. jmeter的线程数,并发用户数,TPS,RPS 关系解说

    背景 在做性能测试的时候,传统方式都是用并发虚拟用户数来衡量系统的性能(站在客户端视角),一般适用于一些网页站点例如首页.H5的压测:而RPS(Requests per second)模式主要是为了方 ...

  9. MySQL如何加锁控制并发

    目录 前言 一.乐观锁 添加version字段 二.悲观锁 读锁 全表锁(LOCK TABLE 表 READ) 行锁(SELECT ... LOCK IN SHARE MODE) 写锁 全表锁(LOC ...

  10. OPTIONS的预请求(Preflighted Request)

    OPTIONS的预请求(Preflighted Request) Ajax 请求中出现OPTIONS(Request Method: OPTIONS)_qiao-CSDN博客 https://blog ...