SPOJ705-New Distinct Substrings-后缀数组

Posted Helica

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SPOJ705-New Distinct Substrings-后缀数组相关的知识,希望对你有一定的参考价值。

计算所都不相同子串的个数,做法是所有子串的个数减去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-后缀数组的主要内容,如果未能解决你的问题,请参考以下文章

Spoj 694 Distinct Substrings

SPOJ Distinct Primes 打表

SPOJ 705 Distinct Substrings(后缀数组)

SPOJ694/DISUBSTR???Distinct Substrings????????????

Distinct Substrings(spoj 694)

SPOJ - DISUBSTR Distinct Substrings