SPOJ DISUBSTR
来源:互联网 发布:百度糯米总显示没网络 编辑:程序博客网 时间:2024/06/14 15:58
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 <= 1000
Output
For each test case output one number saying the number of distinct substrings.
Example
Sample Input:
2
CCCCC
ABABA
Sample Output:
5
9
Explanation for the testcase with string ABABA:
len=1 : A,B
len=2 : AB,BA
len=3 : ABA,BAB
len=4 : ABAB,BABA
len=5 : ABABA
Thus, total number of distinct substrings is 9.
每个子串一定是某个后缀的前缀, 那么原问题等价于求所有后缀之间的不相
同的前缀的个数。如果所有的后缀按照 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)。
#include <iostream>#include <string.h>#include <stdio.h>#include <algorithm>#include <queue>#include <math.h>#include <vector>using namespace std;const int maxn = 1111;int cnt[maxn],sa[maxn],height[maxn],res[maxn],rk[maxn],w[maxn];void getSa(int len,int up){ int *k=rk,*r=res,*id=height; for(int i=0;i<up;i++) cnt[i]=0; for(int i=0;i<len;i++) cnt[k[i]=w[i]]++; for(int i=0;i<up;i++) cnt[i+1]+=cnt[i]; for(int i=len-1;i>=0;i--){ sa[--cnt[k[i]]]=i; } int d=1,p=0; while(p<len){ for(int i=len-d;i<len;i++) id[p++]=i; for(int i=0;i<len;i++) if(sa[i]-d>=0) id[p++]=sa[i]-d; for(int i=0;i<len;i++) r[i]=k[id[i]]; for(int i=0;i<up;i++) cnt[i]=0; for(int i=0;i<len;i++) cnt[r[i]]++; for(int i=0;i<up;i++) cnt[i+1]+=cnt[i]; for(int i=len-1;i>=0;i--){ sa[--cnt[r[i]]]=id[i]; } p=0; swap(k,r); k[sa[0]]=p++; for(int i=0;i<len-1;i++){ if(sa[i]+d<len&&sa[i+1]+d<len&&r[sa[i]]==r[sa[i+1]]&&r[sa[i+1]+d]==r[sa[i]+d]){ k[sa[i+1]]=p-1; } else k[sa[i+1]]=p++; } if(p>=len) return; d=d*2,up=p,p=0; }}void getHeight(int len){ for(int i=0;i<len;i++) rk[sa[i]]=i; height[1]=0; for(int i=0,p=0;i<len-1;i++){ int j=sa[rk[i]-1]; while(i+p<len&&j+p<len&&w[i+p]==w[j+p]) p++; height[rk[i]]=p; p=max(0,p-1); }}void getSuffix(char s[]){ int len=(int)strlen(s); for(int i=0;i<len;i++){ w[i]=s[i]; } w[len++]=0; getSa(len,400); getHeight(len);}void doit(char s[]){ int len=strlen(s); int ans=0; for(int i=1;i<=len;i++){ ans+=len-sa[i]-height[i]; } printf("%d\n",ans);}int main(){ int T; scanf("%d",&T); for(int i=1;i<=T;i++){ char s[maxn]; scanf("%s",s); getSuffix(s); doit(s); }}
- SPOJ DISUBSTR
- SPOJ DISUBSTR
- SPOJ DISUBSTR Distinct Substrings
- SPOJ DISUBSTR Distinct Substrings
- SPOJ DISUBSTR(后缀数组)
- SPOJ - DISUBSTR Distinct Substrings
- SPOJ DISUBSTR Distinct Substrings
- SPOJ DISUBSTR 后缀数组
- SPOJ DISUBSTR 后缀数组
- SPOJ 694 DISUBSTR Distinct Substrings 后缀数组
- [SPOJ DISUBSTR]Distinct Substrings(后缀数组)
- SPOJ DISUBSTR Distinct Substrings (后缀数组)
- 【SPOJ-DISUBSTR】Distinct Substrings【后缀数组】
- 【SPOJ DISUBSTR】Distinct Substrings 后缀数组
- SPOJ DISUBSTR Distinct Substrings(后缀数组)
- SPOJ DISUBSTR Distinct Substrings 后缀数组子串个数
- SPOJ - DISUBSTR 多少个不同的子串
- spoj 694 DISUBSTR - Distinct Substrings (后缀数组)
- 第四章 虚拟机的安装和使用
- 【BZOJ2789】【树状数组】[Poi2012]Letters 题解
- 【二维树状数组】BZOJ1452 [JSOI2009]Count
- 千里之路—— Eclipse开发JAVA,如何新建java项目?
- Linux防火墙开放端口号 及 常用端口号详解
- SPOJ DISUBSTR
- Android中的数据持久化技术
- Unity3d背包系统系统(〇)——功能演示
- bzoj 2073(状压dp)
- 在CENTOS7上玩转Ethereum区块链(5): 实验一--在两台主机上分别部署eth rpc与truffle合约服务
- MySQL安装配置
- Broadcast Receiver使用
- 建立枚举类型Weekday,假设今日为星期二,计算10天后为星期几。
- HTTP协议(转)