SPOJ Distanct Substrings(求不同子串的数量)

Posted songorz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SPOJ Distanct Substrings(求不同子串的数量)相关的知识,希望对你有一定的参考价值。

Given a string, we need to find the total number of its distinct substrings.

Input

T- number of test cases. T<=20;
Each test case consists of one string, whose length is <= 1000

Output

For each test case output one number saying the number of distinct substrings.

Example

Sample Input:
2
CCCCC
ABABA

Sample Output:
5
9

Explanation for the testcase with string ABABA: 
len=1 : A,B
len=2 : AB,BA
len=3 : ABA,BAB
len=4 : ABAB,BABA
len=5 : ABABA
Thus, total number of distinct substrings is 9.

题解:题意就是让你求子串的种类;

思路:后缀数组,然后每个字符的贡献为n-sa[i]-height[i];(n为字符的个数);

参考代码:

技术分享图片
 1 //#include<bits/stdc++.h>
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<string>
 6 #include<cstdlib>
 7 #include<cmath>
 8 #include<algorithm>
 9 using namespace std;
10 #define clr(a,val) memset(a,val,sizeof(a))
11 #define lowbit(x) x&-x
12 #define eps 1e-6
13 typedef long long ll;
14 const int INF=0x3f3f3f3f;
15 const int maxn=1010;
16 struct SuffixArray{
17     int s[maxn];
18     int sa[maxn],height[maxn],rank[maxn],n;
19     int t[maxn*2],t2[maxn*2];
20     int cnt[maxn];
21     void build_sa(int m)//字符都属于0~m-1范围 
22     {
23         int i,*x=t,*y=t2;
24         for(i=0;i<m;i++) cnt[i]=0;
25         for(i=0;i<n;i++) cnt[x[i]=s[i]]++;
26         for(i=1;i<m;i++) cnt[i]+=cnt[i-1];
27         for(i=n-1;i>=0;i--) sa[--cnt[x[i]]]=i; 
28         for(int k=1,p;k<=n;k <<=1)//k<=n
29         {
30             p=0;
31             for(i=n-k;i<n;i++) y[p++]=i;
32             for(i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
33             for(i=0;i<m;i++) cnt[i]=0;
34             for(i=0;i<n;i++) cnt[x[y[i]]]++;
35             for(i=1;i<m;i++) cnt[i]+=cnt[i-1];
36             for(i=n-1;i>=0;i--) sa[--cnt[x[y[i]]]]=y[i];
37             swap(x,y);
38             p=1;x[sa[0]]=0;
39             for(i=1;i<n;i++)
40                    x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]? p-1:p++;
41             if(p>=n) break;
42             m=p;
43         }
44     }
45     void build_height()
46     {
47         int k=0;
48         for(int i=0;i<n;i++) rank[sa[i]]=i;
49         for(int i=0;i<n-1;i++)
50         {
51             if(k) k--;
52             int j=sa[rank[i]-1];
53             while(s[i+k]==s[j+k]) k++;
54             height[rank[i]]=k;
55         }
56     }
57 } SA;
58 int main()
59 {
60     int n, m, t;
61     string str;
62     cin>>t;
63     while(t--) 
64     {
65         cin>>str;
66         int n = str.size();
67         for(int i = 0; i<n; i++) SA.s[i] = str[i];
68         SA.s[n] = 0;SA.n=n+1;
69         SA.build_sa(128);
70         SA.build_height();
71         int ans = 0;
72         for(int i=1;i<=n;i++) ans+=n-SA.sa[i]-SA.height[i];
73         cout<<ans<<endl;
74     }
75     return 0;
76 }
View Code

 

以上是关于SPOJ Distanct Substrings(求不同子串的数量)的主要内容,如果未能解决你的问题,请参考以下文章

Spoj-DISUBSTR - Distinct Substrings~New Distinct Substrings SPOJ - SUBST1~(后缀数组求解子串个数)

Spoj NSUBSTR - Substrings

Spoj 694 Distinct Substrings

spoj8222Substrings

SPOJ 8222 Substrings 后缀自动机

spoj8222 Substrings