spoj694 Distinct Substrings(后缀数组+统计不同子串的个数)
2015-09-14 20:08
309 查看
给定一个字符串,求不相同的子串的个数。
算法分析:
每个子串一定是某个后缀的前缀,那么原问题等价于求所有后缀之间的不相
同的前缀的个数。如果所有的后缀按照 suffix(sa[1]), suffix(sa[2]),
suffix(sa[3]), …… ,suffix(sa
)的顺序计算,不难发现,对于每一次新加
进来的后缀 suffix(sa[k]),它将产生 n-sa[k]+1 个新的前缀。但是其中有
height[k]个是和前面的字符串的前缀是相同的。所以 suffix(sa[k])将“贡献”
出 n-sa[k]+1- height[k]个不同的子串。累加后便是原问题的答案。这个做法
的时间复杂度为 O(n)。
算法分析:
每个子串一定是某个后缀的前缀,那么原问题等价于求所有后缀之间的不相
同的前缀的个数。如果所有的后缀按照 suffix(sa[1]), suffix(sa[2]),
suffix(sa[3]), …… ,suffix(sa
)的顺序计算,不难发现,对于每一次新加
进来的后缀 suffix(sa[k]),它将产生 n-sa[k]+1 个新的前缀。但是其中有
height[k]个是和前面的字符串的前缀是相同的。所以 suffix(sa[k])将“贡献”
出 n-sa[k]+1- height[k]个不同的子串。累加后便是原问题的答案。这个做法
的时间复杂度为 O(n)。
#include<cstdio> #include<algorithm> #include<string> #include<cstring> using namespace std; #define LL long long #define cl(a,b) memset(a,b,size(a)) const int maxn=500002; int n,k; int rank[maxn],tmp[maxn],sa[maxn],lcp[maxn]; char s[maxn]; int cmp(int i,int j){ if(rank[i]!=rank[j])return rank[i]<rank[j]; int ri=i+k<=n?rank[i+k]:-1; int rj=j+k<=n?rank[j+k]:-1; return ri<rj; } void getSa(){ n=strlen(s); for(int i=0;i<=n;i++){ sa[i]=i; rank[i]=i<n?s[i]:-1; } for(k=1;k<=n;k<<=1){ sort(sa,sa+n+1,cmp); tmp[sa[0]]=0; for(int i=1;i<=n;i++){ tmp[sa[i]]=tmp[sa[i-1]]+cmp(sa[i-1],sa[i]); } for(int i=0;i<=n;i++)rank[i]=tmp[i]; } } void getLcp(){ // n=strlen(s); for(int i=0;i<=n;i++)rank[sa[i]]=i; int h=0; lcp[0]=0; for(int i=0;i<n;i++){ int j=sa[rank[i]-1]; if(h>0)h--; while(i+h<n&&j+h<n&&s[i+h]==s[j+h])h++; lcp[rank[i]-1]=h; } } int main(){ int T; scanf("%d",&T); while(T--){ scanf("%s",s); getSa();getLcp(); int ans=n-sa[0]; for(int i=1;i<=n;i++){ ans+=n-sa[i]-lcp[i-1]; } printf("%d\n",ans); } return 0; }
相关文章推荐
- linux nc命令使用详解
- 【前端也要学点数据结构】神奇的树状数组的三大应用
- MySQL性能调优与架构设计——第1章 MySQL 基本介绍
- JAVA中的内部类使用总结
- 问题之~没有规则可以创建 ...需要的目标....
- 三大高级排序
- java中的BigInteger(很好很强大)
- HDU 5441 Travel (带权并查集)
- 进程间、线程间通信方式小结
- 一辈子太短,遗憾却太多
- Android之实用库xUtils四大模块以及用ViewInject代替findViewById()
- 交互式shell和非交互式shell的区别
- Java中的public、protected、default和private的区别
- 【UVA10537】最短路 dijkstra算法
- PHP经典面试题汇总含答案
- hdu5442(2015长春赛区网络赛1006)后缀数组+KMP /最小表示法?
- Centos7安装配置NFS服务和挂载
- Centos 配置eth0 提示Device does not seem to be present
- Hadoop 笔记MuilpleOutputFormat类(将数据写到多个文件中)代码解析
- 开发收获心得