tyvj1860后缀数组
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了tyvj1860后缀数组相关的知识,希望对你有一定的参考价值。
描述
我们定义一个字符串的后缀suffix(i)表示从s[i]到s[length(s)]这段子串。
后缀数组(Suffix array)SA[i]中存放着一个排列,满足suffix(sa[i])<suffix(sa[i+1]) 按照字典序方式比较
定义height[i]表示suffix(sa[i])与suffix(sa[i-1])之间的最长公共前缀长度,其中height[1]=0
你的任务就是求出SA和height这两个数组。字符串长度<=200000
后缀数组(Suffix array)SA[i]中存放着一个排列,满足suffix(sa[i])<suffix(sa[i+1]) 按照字典序方式比较
定义height[i]表示suffix(sa[i])与suffix(sa[i-1])之间的最长公共前缀长度,其中height[1]=0
你的任务就是求出SA和height这两个数组。字符串长度<=200000
输入格式
一行,为描述中的字符串(仅会出现小写字母)
输出格式
共两行,每行n个数,第一行为sa[i],第二行为height[i],其中每行的数均用空格隔开
测试样例1
输入
aabaaaab
输出
4 5 6 1 7 2 8 3题目告诉我们这是一个模板题,这的确就是一个模板题,geth函数还不是太理解。
0 3 2 3 1 2 0 1
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<set> 6 #include<ctime> 7 #include<vector> 8 #include<cmath> 9 #include<algorithm> 10 #include<map> 11 #define inf 2000000000 12 #define N 200005 13 int n; 14 char ch[N]; 15 int a[N],h[N]; 16 int v[N]; 17 int sa[2][N],rk[2][N]; 18 int p,q,k; 19 void init(){ 20 scanf("%s",ch+1); 21 n=strlen(ch+1); 22 for (int i=1;i<=n;i++) a[i]=ch[i]-‘a‘+1; 23 } 24 25 void change(int sa[N],int rk[N],int SA[N],int RK[N]){ 26 for (int i=1;i<=n;i++) v[rk[sa[i]]]=i;//该排名最后出现的位置 27 for (int i=n;i>=1;i--) if (sa[i]>k) 28 SA[v[rk[sa[i]-k]]--]=sa[i]-k;//? 29 for (int i=n-k+1;i<=n;i++) SA[v[rk[i]]--]=i;//? 30 for (int i=1;i<=n;i++) RK[SA[i]]=RK[SA[i-1]]+(rk[SA[i-1]]!=rk[SA[i]]||rk[SA[i-1]+k]!=rk[SA[i]+k]); 31 32 } 33 34 void work(){ 35 q=1,p=0; 36 for (int i=1;i<=n;i++) v[a[i]]++; 37 for (int i=1;i<=26;i++)v[i]+=v[i-1]; 38 for (int i=1;i<=n;i++) sa[p][v[a[i]]--]=i; 39 for (int i=1;i<=n;i++) rk[p][sa[p][i]]=(rk[p][sa[p][i-1]])+(a[sa[p][i-1]]!=a[sa[p][i]]); 40 k=1; 41 while (k<n){ 42 change(sa[p],rk[p],sa[q],rk[q]); 43 p^=1;q^=1;k=k<<1; 44 } 45 for (int i=1;i<=n;i++) printf("%d ",sa[p][i]); 46 } 47 48 void geth(){ 49 int k=0; 50 for (int i=1;i<=n;i++) 51 if (rk[p][i]==1)h[rk[p][i]]=0; 52 else{ 53 int j=sa[p][rk[p][i]-1]; 54 while (a[i+k]==a[j+k])k++; 55 h[rk[p][i]]=k;if (k>0)k--; 56 } 57 } 58 59 int main(){ 60 init(); 61 work(); 62 geth(); 63 puts(""); 64 for(int i=1;i<=n;i++)printf("%d ",h[i]); 65 }
以上是关于tyvj1860后缀数组的主要内容,如果未能解决你的问题,请参考以下文章