码迷,mamicode.com
首页 > 编程语言 > 详细

【tyvj1860】后缀数组

时间:2016-01-23 23:16:11      阅读:441      评论:0      收藏:0      [点我收藏+]

标签:

描述
我们定义一个字符串的后缀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

输入格式

一行,为描述中的字符串(仅会出现小写字母)

输出格式

共两行,每行n个数,第一行为sa[i],第二行为height[i],其中每行的数均用空格隔开

测试样例1

输入

aabaaaab

输出

4 5 6 1 7 2 8 3 
0 3 2 3 1 2 0 1
题目告诉我们这是一个模板题,这的确就是一个模板题,geth函数还不是太理解。
 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】后缀数组

标签:

原文地址:http://www.cnblogs.com/wuminyan/p/5154181.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!