[SPOJ DISUBSTR]Distinct Substrings(后缀数组)
2015-04-08 21:53
369 查看
题目链接
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=19282题目大意
给出一个串,求这个串中有多少个不同的子串。思路
如果计入重复的话,这个串的子串个数为n(n+1)2\frac{n(n+1)}2(一共有nn个后缀,对于以下标tt开头的后缀,有tt个后缀的前缀,就是个等差数列求和)那么现在不计入重复,可以很容易发现,后缀sa[i]sa[i]与后缀sa[i−1]sa[i-1]可能出现一些重复的前缀,重复的前缀个数也显然是height[i]height[i]
代码
记住每次num数组的第n+1位一定要设为0,不然SA的比较过程中可能出错!#include <iostream> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <algorithm> #define MAXN 1100000 using namespace std; int sa[MAXN],rank[MAXN],height[MAXN]; int wa[MAXN],wb[MAXN],wv[MAXN],cnt[MAXN]; bool cmp(int *r,int a,int b,int c) { return (r[a]==r[b])&&(r[a+c]==r[b+c]); } void SA(int *r,int n,int m) { int i,j,p; int *x=wa,*y=wb; for(i=0;i<m;i++) cnt[i]=0; for(i=0;i<n;i++) cnt[(x[i]=r[i])]++; for(i=1;i<m;i++) cnt[i]+=cnt[i-1]; for(i=n-1;i>=0;i--) sa[--cnt[x[i]]]=i; for(j=1,p=1;p<n;j*=2,m=p) { for(p=0,i=n-j;i<n;i++) y[p++]=i; for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j; for(i=0;i<n;i++) wv[i]=x[y[i]]; for(i=0;i<m;i++) cnt[i]=0; for(i=0;i<n;i++) cnt[wv[i]]++; for(i=1;i<m;i++) cnt[i]+=cnt[i-1]; for(i=n-1;i>=0;i--) sa[--cnt[wv[i]]]=y[i]; //!!!!!! swap(x,y); for(p=1,x[sa[0]]=0,i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; } } void calc(int *r,int n) { int i,j,k=0; for(i=1;i<=n;i++) rank[sa[i]]=i; for(i=0;i<n;height[rank[i++]]=k) for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++); } char s[MAXN]; int num[MAXN]; int main() { int T; scanf("%d",&T); while(T--) { scanf("%s",s); int n=strlen(s); for(int i=0;i<=n;i++) num[i]=s[i]; //!!!!! SA(num,n+1,260); calc(num,n); int ans=n*(n+1)/2; for(int i=2;i<=n;i++) ans-=height[i]; printf("%d\n",ans); } return 0; }
相关文章推荐
- spoj 694 DISUBSTR - Distinct Substrings (后缀数组)
- SPOJ DISUBSTR - Distinct Substrings(不同子串数量 后缀数组)
- SPOJ DISUBSTR(后缀数组)
- [SPOJ705]DISUBSTR - Distinct Substrings(后缀数组)
- SPOJ DISUBSTR Distinct Substrings(后缀数组)
- [SPOJ705]DISUBSTR(后缀数组)
- Distinct Substrings SPOJ - DISUBSTR 后缀数组(计算不同的子串数目)
- SPOJ694--- DISUBSTR - Distinct Substrings(后缀数组)
- SPOJ DISUBSTR(后缀数组)
- C - Distinct Substrings SPOJ - DISUBSTR (后缀数组)
- SPOJ DISUBSTR 后缀数组
- SPOJ DISUBSTR ——后缀数组
- SPOJ - DISUBSTR (后缀数组)
- SPOJ694&&SPOJ705 DISUBSTR - Distinct Substrings && SUBST1 - New Distinct Substrings 后缀数组
- [spoj DISUBSTR]后缀数组统计不同子串个数
- SPOJ - DISUBSTR 多少个不同的子串
- SPOJ DISUBSTR 后缀数组
- SPOJ DISUBSTR(字符串hash)
- SPOJ DISUBSTR - Distinct Substrings or SUBST1 - New Distinct Substrings 【不同子串数目】
- SPOJ - DISUBSTR 多少个不同的子串