spoj 694. Distinct Substrings 后缀数组求不同子串的个数

题目链接:http://www.spoj.com/problems/DISUBSTR/

思路:

每个子串一定是某个后缀的前缀,那么原问题等价于求所有后缀之间的不相同的前缀的个数。如果所有的后缀按照suffix(sa[1]),suffix(sa[2]),suffix(sa[3]),……suffix(sa[n])的顺序计算,不难发现,对于每一次新加进来的后缀suffix(sa[k]),它将产生n-sa[k]+1个新的前缀。但是其中有height[k]个是和前面的字符串的前缀是相同的。所以suffix(sa[k])将“贡献”出n-sa[k]+1-height[k]个不同的子串。累加后便是原问题的答案。这个做法的时间复杂度为O(na)。

代码如下:

 1 #include<cstring>
 2 #include<cstdlib>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<iostream>
 6 using namespace std;
 7 const int maxn=1010;
 8 int wa[maxn],wb[maxn],wv[maxn],wq[maxn];
 9 int rank[maxn],sa[maxn];
10 int r[maxn];
11 char s[maxn];
12 int height[maxn];
13 int cmp(int *r,int a,int b,int l)
14 {return r[a]==r[b]&&r[a+l]==r[b+l];}
15 void da(int* r,int *sa,int n,int m)
16 {
17     int i,j,p,*x=wa,*y=wb,*t;
18     for(i=0;i<m;i++) wq[i]=0;
19     for(i=0;i<n;i++) wq[x[i]=r[i]]++;
20     for(i=1;i<m;i++) wq[i]+=wq[i-1];
21     for(i=n-1;i>=0;i--) sa[--wq[x[i]]]=i;
22 
23     for(j=1,p=1;p<n;j*=2,m=p)
24     {
25         for(p=0,i=n-j;i<n;i++) y[p++]=i;
26         for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
27         for(i=0;i<n;i++) wv[i]=x[y[i]];
28         for(i=0;i<m;i++) wq[i]=0;
29         for(i=0;i<n;i++) wq[wv[i]]++;
30         for(i=1;i<m;i++) wq[i]+=wq[i-1];
31         for(i=n-1;i>=0;i--) sa[--wq[wv[i]]]=y[i];
32         for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)
33         x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
34 
35     }
36     return ;
37  
38 }
39 void callheight(int *r,int n)
40 {
41     int i,j,k=0;
42     for(i=1;i<=n;i++) rank[sa[i]]=i;
43     for(i=0;i<n;i++)
44        {
45            if(k) k--;
46            j=sa[rank[i]-1];
47            while(r[i+k]==r[j+k]) k++;
48            height[rank[i]]=k;
49        }
50 }
51 int main()
52  {
53       int t;
54       scanf("%d",&t);
55       while(t--)
56       {
57         scanf("%s",s);
58 
59         int n=strlen(s);
60         for(int i=0;i<n;i++)
61             r[i]=s[i];
62             r[n]=0;
63             da(r,sa,n+1,130);
64             callheight(r,n);
65            int ans=0;
66         for(int i=1;i<=n;i++)
67             ans+=(n-sa[i]-height[i]);
68         cout<<ans<<endl;
69        
70       }
71       return 0;
72  }
View Code
原文地址:https://www.cnblogs.com/xiaozhuyang/p/spoj694.html