模板 后缀数组

(要点写注释里了)代码:求SA

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 int has[2000000];//桶,用于基数排序,ASCII字符集0~127
 5 int sa[2000000];//后缀数组,意为排名为i的后缀起始位置 
 6 int tmr[2000000];//temp_rank为构建rank的临时数组后期需要去重
 7 int rank[2000000];//排名,与sa互为逆映射,为以i起始的后缀的排名 
 8 char str[2000000];
 9 int len,cnt;
10 bool Ssame(int a,int b,int l)//去重函数,意为判断以a,b开始长度为l的子串是否相同 
11 {
12     if(a+l>len||b+l>len)
13         return false;//若有一个末尾超过总长,一定可以判定两串不相同
14     return (rank[a]==rank[b])&&(rank[a+l]==rank[b+l]);//两串排名均相同则相同 
15 }
16 int main()
17 {
18     scanf("%s",str+1);
19     len=strlen(str+1);
20     for(int i=1;i<=len;i++)
21         has[str[i]]++;//构建桶 
22     for(int i=0;i<128;i++)
23         if(has[i])
24             tmr[i]=++cnt;//tmr在第一次构建的时候意为字符所在排名 
25     for(int i=1;i<128;i++)
26         has[i]+=has[i-1];//基数排序参数 
27     for(int i=1;i<=len;i++)
28     {
29         rank[i]=str[i]; 
30         sa[has[str[i]]--]=i;
31     }
32     /*第一次从文本串转化为rank数组,其实是无需离散化的*/
33     for(int k=1;cnt!=len;k*=2)
34     {
35         cnt=0;
36         for(int i=0;i<=len;i++)
37             has[i]=0;//清空 
38         for(int i=1;i<=len;i++)
39             has[rank[i]]++;//本质是rank的排序 
40         for(int i=1;i<=len;i++)
41             has[i]+=has[i-1];//构建桶 
42         for(int i=len;i;i--)//顺序 
43             if(sa[i]>k)
44                 tmr[sa[i]-k]=has[rank[sa[i]-k]]--;//有前半部分 
45         for(int i=1;i<=k;i++)
46             tmr[len-i+1]=has[rank[len-i+1]]--;
47         for(int i=1;i<=len;i++)
48             sa[tmr[i]]=i;
49         for(int i=1;i<=len;i++)
50             if(Ssame(sa[i],sa[i-1],k))
51                 tmr[sa[i]]=cnt;
52             else
53                 tmr[sa[i]]=++cnt;
54         for(int i=1;i<=len;i++)
55             rank[i]=tmr[i];
56     }
57     for(int i=1;i<=len;i++)
58         printf("%d ",sa[i]);
59     puts("");
60     return 0;
61 }

 查询height:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using std::max;
 5 const int N=200000;
 6 int tmr[N];
 7 int rnk[N];
 8 int sa[N];
 9 int has[N];
10 int hgt[N];
11 char str[N];
12 int len;
13 int cnt;
14 bool Same(int a,int b,int l)
15 {
16     if(a+l>len||b+l>len)
17         return false;
18     return (rnk[a]==rnk[b])&&(rnk[a+l]==rnk[b+l]);
19 }
20 int main()
21 {
22     scanf("%s",str+1);
23     len=strlen(str+1);
24     for(int i=1;i<=len;i++)
25         has[str[i]]++;
26     for(int i=0;i<128;i++)
27         if(has[i])
28             tmr[i]=++cnt;
29     for(int i=1;i<128;i++)
30         has[i]+=has[i-1];
31     for(int i=1;i<=len;i++)
32     {
33         rnk[i]=tmr[str[i]];
34         sa[has[str[i]]--]=i;
35     }
36     for(int k=1;cnt!=len;k<<=1)
37     {
38         cnt=0;
39         for(int i=0;i<=len;i++)
40             has[i]=0;
41         for(int i=1;i<=len;i++)
42             has[rnk[i]]++;
43         for(int i=1;i<=len;i++)
44             has[i]+=has[i-1];
45         for(int i=len;i;i--)
46             if(sa[i]>k)
47                 tmr[sa[i]-k]=has[rnk[sa[i]-k]]--;
48         for(int i=1;i<=k;i++)
49             tmr[len-i+1]=has[rnk[len-i+1]]--;
50         for(int i=1;i<=len;i++)
51             sa[tmr[i]]=i;
52         for(int i=1;i<=len;i++)
53             if(Same(sa[i],sa[i-1],k))
54                 tmr[sa[i]]=cnt;
55             else
56                 tmr[sa[i]]=++cnt;
57         for(int i=1;i<=len;i++)
58             rnk[i]=tmr[i];
59     }
60     for(int i=1;i<=len;i++)
61     {
62         if(rnk[i]==1)
63             continue;
64         int j=max(1,hgt[rnk[i-1]]-1);
65         while(str[i+j-1]==str[sa[rnk[i]-1]+j-1])
66             hgt[rnk[i]]=j++;
67     }
68     for(int i=1;i<=len;i++)
69         printf("%d ",sa[i]);
70     puts("");
71     for(int i=2;i<=len;i++)
72         printf("%d ",hgt[i]);
73     puts("");
74     return 0;
75 }

 

posted @ 2018-09-23 20:35  Unstoppable728  阅读(175)  评论(0编辑  收藏  举报