http://www.spoj.com/problems/SUBST1/ (题目链接)

题意

  求字符串的不相同的子串个数

Solution

  后缀数组论文题。

  每个子串一定是某个后缀的前缀,那么原问题等价于求所有后缀之间的不相同的前缀的个数。如果所有的后缀按照 suffix(sa[1]), suffix(sa[2]), suffix(sa[3]), …… ,suffix(sa[n])的顺序计算,不难发现,对于每一次新加进来的后缀suffix(sa[k]),它将产生n-sa[k]+1个新的前缀。但是其中有height[k]个是和前面的字符串的前缀是相同的。所以suffix(sa[k])将“贡献” 出n-sa[k]+1- height[k]个不同的子串。累加后便是原问题的答案。这个做法的时间复杂度为 O(n)。

细节

  开LL

代码

  1. // spoj705
  2. #include<algorithm>
  3. #include<iostream>
  4. #include<cstdlib>
  5. #include<cstring>
  6. #include<vector>
  7. #include<cstdio>
  8. #include<cmath>
  9. #include<set>
  10. #define LL long long
  11. #define inf 1<<30
  12. #define Pi acos(-1.0)
  13. #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
  14. using namespace std;
  15.  
  16. const int maxn=100010;
  17. int sa[maxn],height[maxn],rank[maxn];
  18. char s[maxn];
  19.  
  20. namespace Suffix {
  21. int wa[maxn],wb[maxn],ww[maxn];
  22. bool cmp(int *r,int a,int b,int l) {
  23. return r[a]==r[b] && r[a+l]==r[b+l];
  24. }
  25. void da(char *r,int *sa,int n,int m) {
  26. int i,j,p,*x=wa,*y=wb;
  27. for (i=0;i<=m;i++) ww[i]=0;
  28. for (i=1;i<=n;i++) ww[x[i]=r[i]]++;
  29. for (i=1;i<=m;i++) ww[i]+=ww[i-1];
  30. for (i=n;i>=1;i--) sa[ww[x[i]]--]=i;
  31. for (p=0,j=1;p<n;j*=2,m=p) {
  32. for (p=0,i=n-j+1;i<=n;i++) y[++p]=i;
  33. for (i=1;i<=n;i++) if (sa[i]>j) y[++p]=sa[i]-j;
  34. for (i=0;i<=m;i++) ww[i]=0;
  35. for (i=1;i<=n;i++) ww[x[y[i]]]++;
  36. for (i=1;i<=m;i++) ww[i]+=ww[i-1];
  37. for (i=n;i>=1;i--) sa[ww[x[y[i]]]--]=y[i];
  38. for (swap(x,y),p=x[sa[1]]=1,i=2;i<=n;i++) {
  39. x[sa[i]]=cmp(y,sa[i-1],sa[i],j) ? p : ++p;
  40. }
  41. }
  42. }
  43. void calheight(char *r,int *sa,int n) {
  44. for (int i=1;i<=n;i++) rank[sa[i]]=i;
  45. for (int k=0,i=1;i<=n;i++) {
  46. if (k) k--;
  47. int j=sa[rank[i]-1];
  48. while (r[i+k]==r[j+k]) k++;
  49. height[rank[i]]=k;
  50. }
  51. }
  52. }
  53. int main() {
  54. int T;scanf("%d",&T);
  55. while (T--) {
  56. scanf("%s",s+1);
  57. int n=strlen(s+1);
  58. Suffix::da(s,sa,n,300);
  59. Suffix::calheight(s,sa,n);
  60. LL ans=0;
  61. for (int i=1;i<=n;i++) ans+=(n-sa[i]+1)-height[i];
  62. printf("%lld\n",ans);
  63. }
  64. return 0;
  65. }

【spoj SUBST1】 New Distinct Substrings的更多相关文章

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

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

  2. SPOJ - SUBST1 D - New Distinct Substrings

    D - New Distinct Substrings 题目大意:求一个字符串中不同子串的个数. 裸的后缀数组 #include<bits/stdc++.h> #define LL lon ...

  3. [SPOJ]DISUBSTR:Distinct Substrings&[SPOJ]SUBST1:New Distinct Substrings

    题面 Vjudge Vjudge Sol 求一个串不同子串的个数 每个子串一定是某个后缀的前缀,也就是求所有后缀不同前缀的个数 每来一个后缀\(suf(i)\)就会有,\(len-sa[i]+1\)的 ...

  4. 【 SPOJ - GRASSPLA】 Grass Planting (树链剖分+树状数组)

    54  种草约翰有 N 个牧场,编号为 1 到 N.它们之间有 N − 1 条道路,每条道路连接两个牧场.通过这些道路,所有牧场都是连通的.刚开始的时候,所有道路都是光秃秃的,没有青草.约翰会在一些道 ...

  5. SPOJ 题目705 New Distinct Substrings(后缀数组,求不同的子串个数)

    SUBST1 - New Distinct Substrings no tags  Given a string, we need to find the total number of its di ...

  6. 【Codeforces 258D】 Count Good Substrings

    [题目链接] http://codeforces.com/contest/451/problem/D [算法] 合并后的字符串一定是形如"ababa","babab&qu ...

  7. 【SPOJ 694】Distinct Substrings (更直接的求法)

    [链接]h在这里写链接 [题意] 接上一篇文章 [题解] 一个字符串所有不同的子串的个数=∑(len-sa[i]-height[i]) [错的次数] 0 [反思] 在这了写反思 [代码] #inclu ...

  8. 【SPOJ 694】Distinct Substrings

    [链接]h在这里写链接 [题意]     给你一个长度最多为1000的字符串     让你求出一个数x,这个x=这个字符串的不同子串个数; [题解]     后缀数组题.     把原串复制一份,加在 ...

  9. 【SPOJ】694. Distinct Substrings

    http://www.spoj.com/problems/DISUBSTR/ 题意:求字符串不同子串的数目. #include <bits/stdc++.h> using namespac ...

随机推荐

  1. 解决java读取大文件内存溢出问题

    1. 传统方式:在内存中读取文件内容 读取文件行的标准方式是在内存中读取,Guava 和Apache Commons IO都提供了如下所示快速读取文件行的方法: Files.readLines(new ...

  2. java事务 深入Java事务的原理与应用

    一.什么是JAVA事务 通常的观念认为,事务仅与数据库相关. 事务必须服从ISO/IEC所制定的ACID原则.ACID是原子性(atomicity).一致性(consistency).隔离性 (iso ...

  3. 多表查询sql语句

    多表查询sql语句 1 --解锁SCOTT用户 2 alter user scott account unlock 3 --检索指定的列 4 select job,ename,empno from e ...

  4. Hyperledger Fabric 1.2 --- Chaincode Operator 解读和测试(二)

    本文接上一节是测试部分 搭建一个模拟测试环境 作者将fabric release1.2工程中的 example-e2e进行了改造来进行本次实验: (1)首先我们将examples/e2e_cli/sc ...

  5. js备忘录1

    新建对象 赋值和取值操作 var book={ topic:"JavaScript", fat: true }; book.topic  通过点访问 book["fat& ...

  6. do...while和while...do的两种场景比较

    场景:脚本每5分钟执行一次,从数据库中每次查询1000数据进行处理,直到处理结束.两种用while和do...while两种方式实现的伪代码如下: 1. while...do $count = mys ...

  7. ### Error building SqlSession.

    org.apache.ibatis.exceptions.PersistenceException: ### Error building SqlSession.### The error may e ...

  8. Leetcode题库——17.电话号码的字母组合

    @author: ZZQ @software: PyCharm @file: letterCombinations.py @time: 2018/10/18 18:33 要求:给定一个仅包含数字 2- ...

  9. 【CS231N】2、多类SVM

    一.疑问 1. assignments1 linear_svm.py文件的函数 svm_loss_naive中,使用循环的方式实现梯度计算 linear_svm.py文件的函数 svm_loss_ve ...

  10. 18_集合框架_第18天_集合、Iterator迭代器、增强for循环 、泛型_讲义

    今日内容介绍 1.集合 2.Iterator迭代器 3.增强for循环 4.泛型 01集合使用的回顾 *A:集合使用的回顾 *a.ArrayList集合存储5个int类型元素 public stati ...