题意:求字符串中不同子串的个数。

解题关键:每个子串一定是某个后缀的前缀,那么原问题等价于求所有后缀之间的不相同的前缀的个数。

1、总数减去height数组的和即可。

注意这里height中为什么不需要进行组合计数,因为,每一个height的左端点已经确定,所以只需变动右端点,总共$height[i]$种情况。

2、如果所有的后缀按照 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)。

类似于dp的过程

法一:

  1. #include <cstdlib>
  2. #include <cstring>
  3. #include <cstdio>
  4. #include <algorithm>
  5. #include<iostream>
  6. #include<cmath>
  7. #define inf 0x3f3f3f3f
  8. typedef long long ll;
  9. using namespace std;
  10. const int N=;
  11. int wa[N],wb[N],wv[N],wc[N];
  12. bool cmp(int *r,int a,int b,int l){return r[a]==r[b]&&r[a+l]==r[b+l];}
  13. void make_sa(int *r,int *sa,int n,int m){
  14. int i,j,p,*x=wa,*y=wb;
  15. for(i=;i<m;i++) wc[i]=;
  16. for(i=;i<n;i++) wc[x[i]=r[i]]++;
  17. for(i=;i<m;i++) wc[i]+=wc[i-];
  18. for(i=n-;i>=;i--) sa[--wc[x[i]]]=i;
  19. for(j=,p=;p<n;j*=,m=p){
  20. for(p=,i=n-j;i<n;i++) y[p++]=i;
  21. for(i=;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
  22. for(i=;i<n;i++) wv[i]=x[y[i]];
  23. for(i=;i<m;i++) wc[i]=;
  24. for(i=;i<n;i++) wc[wv[i]]++;
  25. for(i=;i<m;i++) wc[i]+=wc[i-];
  26. for(i=n-;i>=;i--) sa[--wc[wv[i]]]=y[i];
  27. for(swap(x,y),p=,x[sa[]]=,i=;i<n;i++) x[sa[i]]=cmp(y,sa[i-],sa[i],j)?p-:p++;
  28. }
  29. return;
  30. }
  31. int rank1[N],height[N],sa[N];
  32. void make_height(int *r,int *sa,int n){
  33. int i,j,k=;
  34. for(i=;i<=n;i++) rank1[sa[i]]=i;
  35. for(i=;i<n;height[rank1[i++]]=k)
  36. for(k?k--:,j=sa[rank1[i]-];r[i+k]==r[j+k];k++);
  37. return;
  38. }
  39.  
  40. int n,k,r[N];
  41. int main(){
  42. int t;
  43. ios::sync_with_stdio();
  44. cin>>t;
  45. while(t--){
  46. string s;
  47. cin>>s;
  48. for(int i=;i<s.size();i++) r[i]=(int)s[i];
  49. r[s.size()]=;
  50. n=s.size();
  51. make_sa(r,sa,n+,);
  52. make_height(r,sa,n);
  53. ll sum=s.size()*(s.size()+)/;
  54. for(int i=;i<=n;i++){
  55. sum-=height[i];
  56. }
  57. cout<<sum<<"\n";
  58. }
  59. return ;
  60. }

法二:

  1. #include <cstdlib>
  2. #include <cstring>
  3. #include <cstdio>
  4. #include <algorithm>
  5. #include<iostream>
  6. #include<cmath>
  7. #define inf 0x3f3f3f3f
  8. typedef long long ll;
  9. using namespace std;
  10. const int N=;
  11. int wa[N],wb[N],wv[N],wc[N];
  12. bool cmp(int *r,int a,int b,int l){return r[a]==r[b]&&r[a+l]==r[b+l];}
  13. void make_sa(int *r,int *sa,int n,int m){
  14. int i,j,p,*x=wa,*y=wb;
  15. for(i=;i<m;i++) wc[i]=;
  16. for(i=;i<n;i++) wc[x[i]=r[i]]++;
  17. for(i=;i<m;i++) wc[i]+=wc[i-];
  18. for(i=n-;i>=;i--) sa[--wc[x[i]]]=i;
  19. for(j=,p=;p<n;j*=,m=p){
  20. for(p=,i=n-j;i<n;i++) y[p++]=i;
  21. for(i=;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
  22. for(i=;i<n;i++) wv[i]=x[y[i]];
  23. for(i=;i<m;i++) wc[i]=;
  24. for(i=;i<n;i++) wc[wv[i]]++;
  25. for(i=;i<m;i++) wc[i]+=wc[i-];
  26. for(i=n-;i>=;i--) sa[--wc[wv[i]]]=y[i];
  27. for(swap(x,y),p=,x[sa[]]=,i=;i<n;i++) x[sa[i]]=cmp(y,sa[i-],sa[i],j)?p-:p++;
  28. }
  29. return;
  30. }
  31. int rank1[N],height[N],sa[N];
  32. void make_height(int *r,int *sa,int n){
  33. int i,j,k=;
  34. for(i=;i<=n;i++) rank1[sa[i]]=i;
  35. for(i=;i<n;height[rank1[i++]]=k)
  36. for(k?k--:,j=sa[rank1[i]-];r[i+k]==r[j+k];k++);
  37. return;
  38. }
  39.  
  40. int n,k,r[N];
  41. int main(){
  42. int t;
  43. ios::sync_with_stdio();
  44. cin>>t;
  45. while(t--){
  46. string s;
  47. cin>>s;
  48. for(int i=;i<s.size();i++) r[i]=(int)s[i];
  49. r[s.size()]=;
  50. n=s.size();
  51. make_sa(r,sa,n+,);
  52. make_height(r,sa,n);
  53. int sum=;
  54. for(int i=;i<=n;i++){
  55. sum+=n-sa[i]-height[i];
  56. }
  57. cout<<sum<<"\n";
  58. }
  59. return ;
  60. }

另:整理下DC3模板(r和sa

  1. #include<cstdlib>
  2. #include<cstring>
  3. #include<cstdio>
  4. #include<algorithm>
  5. #include<iostream>
  6. #include<cmath>
  7. #define inf 0x3f3f3f3f
  8. typedef long long ll;
  9. using namespace std;
  10. const int N=;
  11. #define F(x) ((x)/3+((x)%3==1?0:tb))
  12. #define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)
  13. int wa[N],wb[N],wv[N],ws1[N];
  14. int c0(int *r,int a,int b){ return r[a]==r[b]&&r[a+]==r[b+]&&r[a+]==r[b+]; }
  15. int c12(int k,int *r,int a,int b){
  16. if(k==) return r[a]<r[b]||r[a]==r[b]&&c12(,r,a+,b+);
  17. else return r[a]<r[b]||r[a]==r[b]&&wv[a+]<wv[b+];
  18. }
  19. void sort(int *r,int *a,int *b,int n,int m){
  20. int i;
  21. for(i=;i<n;i++) wv[i]=r[a[i]];
  22. for(i=;i<m;i++) ws1[i]=;
  23. for(i=;i<n;i++) ws1[wv[i]]++;
  24. for(i=;i<m;i++) ws1[i]+=ws1[i-];
  25. for(i=n-;i>=;i--) b[--ws1[wv[i]]]=a[i];
  26. return;
  27. }
  28. void dc3(int *r,int *sa,int n,int m){
  29. int i,j,*rn=r+n,*san=sa+n,ta=,tb=(n+)/,tbc=,p;
  30. r[n]=r[n+]=;
  31. for(i=;i<n;i++) if(i%!=) wa[tbc++]=i;
  32. sort(r+,wa,wb,tbc,m);
  33. sort(r+,wb,wa,tbc,m);
  34. sort(r,wa,wb,tbc,m);
  35. for(p=,rn[F(wb[])]=,i=;i<tbc;i++)
  36. rn[F(wb[i])]=c0(r,wb[i-],wb[i])?p-:p++;
  37. if(p<tbc) dc3(rn,san,tbc,p);
  38. else for(i=;i<tbc;i++) san[rn[i]]=i;
  39. for(i=;i<tbc;i++) if(san[i]<tb) wb[ta++]=san[i]*;
  40. if(n%==) wb[ta++]=n-;
  41. sort(r,wb,wa,ta,m);
  42. for(i=;i<tbc;i++) wv[wb[i]=G(san[i])]=i;
  43. for(i=,j=,p=;i<ta && j<tbc;p++)
  44. sa[p]=c12(wb[j]%,r,wa[i],wb[j])?wa[i++]:wb[j++];
  45. for(;i<ta;p++) sa[p]=wa[i++];
  46. for(;j<tbc;p++) sa[p]=wb[j++];
  47. return;
  48. }
  49. int rank1[N],height[N],sa[*N];
  50. void make_height(int *r,int *sa,int n){
  51. int i,j,k=;
  52. for(i=;i<=n;i++) rank1[sa[i]]=i;
  53. for(i=;i<n;height[rank1[i++]]=k)
  54. for(k?k--:,j=sa[rank1[i]-];r[i+k]==r[j+k];k++);
  55. return;
  56. }
  57.  
  58. int n,k,r[*N];
  59. int main(){
  60. int t;
  61. ios::sync_with_stdio();
  62. cin>>t;
  63. while(t--){
  64. string s;
  65. cin>>s;
  66. for(int i=;i<s.size();i++) r[i]=(int)s[i];
  67. r[s.size()]=;
  68. n=s.size();
  69. dc3(r,sa,n+,);
  70. make_height(r,sa,n);
  71. int sum=;
  72. for(int i=;i<=n;i++){
  73. sum+=n-sa[i]-height[i];
  74. }
  75. cout<<sum<<"\n";
  76. }
  77. return ;
  78. }

必须开到3倍大小)

[spoj694&spoj705]New Distinct Substrings(后缀数组)的更多相关文章

  1. SPOJ - SUBST1 New Distinct Substrings —— 后缀数组 单个字符串的子串个数

    题目链接:https://vjudge.net/problem/SPOJ-SUBST1 SUBST1 - New Distinct Substrings #suffix-array-8 Given a ...

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

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

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

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

  4. SPOJ DISUBSTR Distinct Substrings 后缀数组

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

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

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

  6. spoj Distinct Substrings 后缀数组

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

  7. spoj 694. Distinct Substrings 后缀数组求不同子串的个数

    题目链接:http://www.spoj.com/problems/DISUBSTR/ 思路: 每个子串一定是某个后缀的前缀,那么原问题等价于求所有后缀之间的不相同的前缀的个数.如果所有的后缀按照su ...

  8. SPOJ_705_New Distinct Substrings_后缀数组

    SPOJ_705_New Distinct Substrings_后缀数组 题意: 给定一个字符串,求该字符串含有的本质不同的子串数量. 后缀数组的一个小应用. 考虑每个后缀的贡献,如果不要求本质不同 ...

  9. Cogs 1709. [SPOJ705]不同的子串 后缀数组

    题目:http://cojs.tk/cogs/problem/problem.php?pid=1709 1709. [SPOJ705]不同的子串 ★★   输入文件:subst1.in   输出文件: ...

随机推荐

  1. asm 与 cglib(整理的)

    参考博客地址 http://www.oseye.net/user/kevin/blog/304#top http://www.blogjava.net/vanadies10/archive/2011/ ...

  2. EF6&EFCore 注册/使用实体类的正确姿势

    首先回顾下EF中常规使用流程 1.新建实体类以及实体配置(data annotation或fluent api) [Table("Users")] public class Use ...

  3. 转载 -- iOS开发之JSON格式数据的生成与解析

    本文将从四个方面对IOS开发中JSON格式数据的生成与解析进行讲解: 一.JSON是什么? 二.我们为什么要用JSON格式的数据? 三.如何生成JSON格式的数据? 四.如何解析JSON格式的数据? ...

  4. C#抓取网面上的html内容(JS动态生成的无法抓取)

    抓取内容的代码: /// </summary> /// <param name="url">路径URL</param> /// <para ...

  5. windows下MySQL 5.7+ 解压缩版安装配置方法(转,写的很简单精辟 赞)

    方法来自伟大的互联网. 1.去官网下载.zip格式的MySQL Server的压缩包,根据需要选择x86或x64版.注意:下载是需要注册账户并登录的. 2.解压缩至你想要的位置. 3.复制解压目录下m ...

  6. JS之字符串与JSON转换

    JS之字符串转换JSON 1.eval   古老的方式 function strToJson(str){ var json = eval('(' + str + ')'); return json; ...

  7. global 全局变量的用法

    说明:i 和foo()都为全局变量,i 是在模块文件顶层注册的,所以为全局变量,他能够在函数内部进行引用而不需要再特意声明是全局变量,且foo()函数也是全局变量 1.当没有局部变量时,print(i ...

  8. main方法的参数

    敲例子的时候无意中把主方法的参数给落下了,当时没有发现,保存之后就去编译,运行了,通常情况下编译没有错误那胜利就在掌握之中了,没想到这次我竟然在"不一般"的行列中,编译无误,运行出 ...

  9. iPad actionsjeet

    在iphone和ipad上使用UIActionShee控件t的效果会不一样,在苹果的官方文档中有相关说明: 在ipad上使用UIActionSheet控件改控件不再从底部弹出,而是从屏幕中间弹出与UI ...

  10. SQL 数据类型 numeric varchar char

    Numeric(10,2) 指字段是数字型,长度为10 小数为两位的 简要描述一下SQL中的五种数据类型:字符型,文本型,数值型,逻辑型和日期型 字符型 VARCHAR VS CHAR VARCHAR ...