题目链接:https://vjudge.net/problem/SPOJ-SUBST1

SUBST1 - New 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 <= 50000

Output

For each test case output one number saying the number of distinct substrings.

Example

  1. Input:
  2. 2
  3. CCCCC
  4. ABABA
  5.  
  6. Output:
  7. 5
  8. 9

题意:

给出一个字符串,求这个字符串有多少种子串?

方法一:

方法二:

1.先不考虑重复的,那么长度为n的字符串,有n+(n-1)+……1 = n*(n+1)/2个子串。

2.然后再考虑重复出现的,即去重。利用后缀数组,求出height数组,那么减去∑height[i],即为答案。为何?

height[i]的定义:排名第i与排名第i-1的后缀的最长公共前缀。那么对于以sa[i](下标)为左端点的一群子串,最多有height[i]个是在以sa[i-1]为左端点的一群子串中出现过的,因此需要减去height[i]。并且排名相邻的子串,前缀的重叠率是最高的,因此不会出现遗漏。枚举每个height,即枚举每个左端点,即可减去所有重复出现的。

代码如下:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <algorithm>
  5. #include <vector>
  6. #include <cmath>
  7. #include <queue>
  8. #include <stack>
  9. #include <map>
  10. #include <string>
  11. #include <set>
  12. using namespace std;
  13. typedef long long LL;
  14. const double EPS = 1e-;
  15. const int INF = 2e9;
  16. const LL LNF = 9e18;
  17. const int MOD = 1e5;
  18. const int MAXN = 5e4+;
  19.  
  20. bool cmp(int *r, int a, int b, int l)
  21. {
  22. return r[a]==r[b] && r[a+l]==r[b+l];
  23. }
  24.  
  25. int t1[MAXN], t2[MAXN], c[MAXN];
  26. void DA(int str[], int sa[], int Rank[], int height[], int n, int m)
  27. {
  28. n++;
  29. int i, j, p, *x = t1, *y = t2;
  30. for(i = ; i<m; i++) c[i] = ;
  31. for(i = ; i<n; i++) c[x[i] = str[i]]++;
  32. for(i = ; i<m; i++) c[i] += c[i-];
  33. for(i = n-; i>=; i--) sa[--c[x[i]]] = i;
  34. for(j = ; j<=n; j <<= )
  35. {
  36. p = ;
  37. for(i = n-j; i<n; i++) y[p++] = i;
  38. for(i = ; i<n; i++) if(sa[i]>=j) y[p++] = sa[i]-j;
  39.  
  40. for(i = ; i<m; i++) c[i] = ;
  41. for(i = ; i<n; i++) c[x[y[i]]]++;
  42. for(i = ; i<m; i++) c[i] += c[i-];
  43. for(i = n-; i>=; i--) sa[--c[x[y[i]]]] = y[i];
  44.  
  45. swap(x, y);
  46. p = ; x[sa[]] = ;
  47. for(i = ; i<n; i++)
  48. x[sa[i]] = cmp(y, sa[i-], sa[i], j)?p-:p++;
  49. if(p>=n) break;
  50. m = p;
  51. }
  52.  
  53. int k = ;
  54. n--;
  55. for(i = ; i<=n; i++) Rank[sa[i]] = i;
  56. for(i = ; i<n; i++)
  57. {
  58. if(k) k--;
  59. j = sa[Rank[i]-];
  60. while(str[i+k]==str[j+k]) k++;
  61. height[Rank[i]] = k;
  62. }
  63. }
  64.  
  65. char str[MAXN];
  66. int r[MAXN], sa[MAXN], Rank[MAXN], height[MAXN];
  67. int main()
  68. {
  69. int T;
  70. scanf("%d", &T);
  71. while(T--)
  72. {
  73. scanf("%s", str);
  74. int len = strlen(str);
  75. for(int i = ; i<len; i++)
  76. r[i] = str[i];
  77. r[len] = ;
  78. DA(r, sa, Rank, height, len, );
  79.  
  80. /* 方法一:
  81. LL ans = 0;
  82. for(int i = 1; i<=len; i++)
  83. ans += len-sa[i]-height[i];
  84. */
  85. // 方法二:
  86. LL ans = 1LL*len*(len+)/;
  87. for(int i = ; i<=len; i++)
  88. ans -= height[i];
  89.  
  90. printf("%lld\n", ans);
  91. }
  92. }

SPOJ - SUBST1 New Distinct Substrings —— 后缀数组 单个字符串的子串个数的更多相关文章

  1. SPOJ 694 || 705 Distinct Substrings ( 后缀数组 && 不同子串的个数 )

    题意 : 对于给出的串,输出其不同长度的子串的种类数 分析 : 有一个事实就是每一个子串必定是某一个后缀的前缀,换句话说就是每一个后缀的的每一个前缀都代表着一个子串,那么如何在这么多子串or后缀的前缀 ...

  2. POJ3415 Common Substrings —— 后缀数组 + 单调栈 公共子串个数

    题目链接:https://vjudge.net/problem/POJ-3415 Common Substrings Time Limit: 5000MS   Memory Limit: 65536K ...

  3. SPOJ SUBST1 New Distinct Substrings(后缀数组 本质不同子串个数)题解

    题意: 问给定串有多少本质不同的子串? 思路: 子串必是某一后缀的前缀,假如是某一后缀\(sa[k]\),那么会有\(n - sa[k] + 1\)个前缀,但是其中有\(height[k]\)个和上一 ...

  4. SPOJ - DISUBSTR Distinct Substrings (后缀数组)

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

  5. SPOJ DISUBSTR Distinct Substrings 后缀数组

    题意:统计母串中包含多少不同的子串 然后这是09年论文<后缀数组——处理字符串的有力工具>中有介绍 公式如下: 原理就是加上新的,减去重的,这题是因为打多校才补的,只能说我是个垃圾 #in ...

  6. 后缀数组:SPOJ SUBST1 - New Distinct Substrings

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

  7. 【SPOJ – SUBST1】New Distinct Substrings 后缀数组

    New Distinct Substrings 题意 给出T个字符串,问每个字符串有多少个不同的子串. 思路 字符串所有子串,可以看做由所有后缀的前缀组成. 按照后缀排序,遍历后缀,每次新增的前缀就是 ...

  8. spoj Distinct Substrings 后缀数组

    给定一个字符串,求不相同的子串的个数. 假如给字符串“ABA";排列的子串可能: A B A AB  BA ABA 共3*(3+1)/2=6种; 后缀数组表示时: A ABA BA 对于A和 ...

  9. Spoj SUBST1 New Distinct Substrings

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

随机推荐

  1. Spring3和Quartz2的应用实例

    /** * 任务调度类 * @author Joyce.Luo * @date 2015-3-31 下午03:32:04 * @version V3.0 * @since Tomcat6.0,Jdk1 ...

  2. Android 使用意图播放本地视频

    Android播放视频的方式有三种: 一.使用意图播放,调用本地安装的播放器,选择一个进行播放. 二.使用VideoView播放(VideoView事实上是对MediaPlayer的封装,使用起来非常 ...

  3. centos DHCP

    yum install dhcp cat /usr/share/doc/dhcp-4.2.5/dhcpd.conf.example > /etc/dhcp/dhcpd.conf vim /etc ...

  4. Python例子二

    例1.构造函数 #-*-coding:utf--*- import sys class Student: def __init__(self,name,age): self.__name=name s ...

  5. VMware-Fusion-7.0.0-2103067 Pro SN:序列号+ 百度云下载地址

    VMware-Fusion-7.0.0-2103067Pro SN: 5CQE9-H5PY3-04ND5-4Z6EW-3QGDE JZCNC-2H9X9-44TD9-Y0X5W-2KGP5 8ZNTC ...

  6. Spring Cloud Zuul API服务网关之请求路由

    目录 一.Zuul 介绍 二.构建Spring Cloud Zuul网关 构建网关 请求路由 请求过滤 三.路由详解 一.Zuul 介绍 ​ 通过前几篇文章的介绍,我们了解了Spring Cloud ...

  7. c# emit 实现类的代理

    using System; using System.Linq; using System.Reflection; using System.Reflection.Emit; namespace Em ...

  8. jquery判断复选框是否被选中

    $("#isUse").click(function(){ if($(this).is(':checked')){ $(this).attr('checked','checked' ...

  9. cocos2d-x 下使用加密 sqlite3

    sqlite3 加密库用的是wxsqlite3-3.0.0.1 提取出来的, 在android 下測试通过,无异常 编译时仅仅须要编译  sqlite3secure.c  此文件,即能够成功.測试时生 ...

  10. alibaba canal安装笔记

    canal是alibaba开源的基于mysql binlog解析工具,可利用它实现mysql增量订阅/消费,典型的应用场景如下图: 利用canal,可以将mysql的数据变化,通过解析binlog,投 ...