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

SPOJ705-New Distinct Substrings-后缀数组

时间:2016-05-19 23:18:14      阅读:232      评论:0      收藏:0      [点我收藏+]

标签:

计算所都不相同子串的个数,做法是所有子串的个数减去sigma(height[]).其中height数组的和便是所有相同子串的个数。

注意 N×(N+1)/2会爆int!但是最终答案在int内。所以使用sigma(n-sa[i]+1-height[i])的做法不会wa

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 
 5 using namespace std;
 6 
 7 const int maxn = 5e4+10;
 8 char line[maxn];
 9 int s[maxn];
10 int sa[maxn],t1[maxn],t2[maxn],c[maxn];
11 int rank[maxn],height[maxn];
12 
13 void build_sa(int s[],int n,int m)
14 {
15     int i,j,p,*x=t1,*y=t2;
16     //第一轮基数排序,如果s的最大值很大,可改为快速排序
17     for(i=0;i<m;i++)c[i]=0;
18     for(i=0;i<n;i++)c[x[i]=s[i]]++;
19     for(i=1;i<m;i++)c[i]+=c[i-1];
20     for(i=n-1;i>=0;i--)sa[--c[x[i]]]=i;
21     for(j=1;j<=n;j<<=1)
22     {
23         p=0;
24         //直接利用sa数组排序第二关键字
25         for(i=n-j;i<n;i++)y[p++]=i;//后面的j个数第二关键字为空的最小
26         for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j;
27         //这样数组y保存的就是按照第二关键字排序的结果
28         //基数排序第一关键字
29         for(i=0;i<m;i++)c[i]=0;
30         for(i=0;i<n;i++)c[x[y[i]]]++;
31         for(i=1;i<m;i++)c[i]+=c[i-1];
32         for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i];
33         //根据sa和x数组计算新的x数组
34         swap(x,y);
35         p=1;x[sa[0]]=0;
36         for(i=1;i<n;i++)
37             x[sa[i]]=y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+j]==y[sa[i]+j]?p-1:p++;
38         if(p>=n)break;
39         m=p;//下次基数排序的最大值
40     }
41 }
42 void getHeight(int s[],int n)
43 {
44     int i,j,k=0;
45     for(i=0;i<=n;i++)rank[sa[i]]=i;
46     for(i=0;i<n;i++)
47     {
48         if(k)k--;
49         j=sa[rank[i]-1];
50         while(s[i+k]==s[j+k])k++;
51         height[rank[i]]=k;
52     }
53 }
54 
55 int T;
56 
57 int main()
58 {
59     scanf("%d",&T);
60     while(T--)
61     {
62         scanf("%s",line);
63         int N = strlen(line);
64         for(int i=0;i<=N;i++)
65             s[i] = line[i];
66 
67         build_sa(s,N+1,300);
68         getHeight(s,N);
69 
70         long long len = N;
71         long long ans = len*(len+1)/2;
72 
73         for(int i=2;i<=N;i++)
74         {
75             ans -= height[i];
76         }
77         printf("%d\n",ans);
78     }
79 }

 

SPOJ705-New Distinct Substrings-后缀数组

标签:

原文地址:http://www.cnblogs.com/helica/p/5510436.html

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